2013-07-05 6 views
11

나는 현재 방이나 whaterever 내에서 사용자의 움직임 궤적을 그릴 수있는 추적 시스템을 개발 중이다.작은 마커 이미지를 그려 내 맞춤 맵 이미지에서 위치를 새로 고치는 방법은 무엇입니까? - 안드로이드

이제지도를 앱으로 가져올 수 있으며지도를 자유롭게 확대/축소하고 이동할 수 있습니다. 다음 단계는지도에서 사용자 위치를 나타내는 마커를 배치하고지도 주위로 마크를 이동하는 것입니다. (지도에 떠있는 것 같이)

나는 이것을 어쩌면 MyLocationOverlay과 함께 할 수 있다고 생각하지만 대부분의 예제는 모두 google map에 적용 할 것입니다. 그러나, 나의 경우, 내지도는 google map이 아니며, 나의지도입니다. (지도는 내 방의지도 또는 내가 직접 그림을 그릴 수있는지도입니다.)

추적 알고리즘을 수행했습니다. 즉, 내 마커 영상을 배치 할 위치를 알고 있습니다..

이렇게 유일한 문제는지도 이미지 위에 마커 이미지를 표시하는 방법입니다. 다음과 같이 세부

, 나는, 자기 정의보기,지도보기 있습니다

package com.example.drsystem; 

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.drawable.Drawable; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.ScaleGestureDetector; 
import android.view.View; 

public class MapView extends View { 

    private static final int INVALID_POINTER_ID = -1; 

    private Drawable mImage; 
    private float mPosX; 
    private float mPosY; 

    private float mLastTouchX; 
    private float mLastTouchY; 
    private int mActivePointerId = INVALID_POINTER_ID; 

    private ScaleGestureDetector mScaleDetector; 
    private float mScaleFactor = 1.f; 

    public MapView(Context context) { 
     this(context, null, 0); 

     mImage = getResources().getDrawable(R.drawable.lv12n); 
     mImage.setBounds(0, 0, mImage.getIntrinsicWidth(), mImage.getIntrinsicHeight()); 
    } 

    // called when XML tries to inflate this View 
    public MapView(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 

     mImage = getResources().getDrawable(R.drawable.lv12n); 
     mImage.setBounds(0, 0, mImage.getIntrinsicWidth(), mImage.getIntrinsicHeight()); 
    } 

    public MapView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
     // Let the ScaleGestureDetector inspect all events. 
     mScaleDetector.onTouchEvent(ev); 

     final int action = ev.getAction(); 
     switch (action & MotionEvent.ACTION_MASK) { 
     case MotionEvent.ACTION_DOWN: { 
      final float x = ev.getX(); 
      final float y = ev.getY(); 

      mLastTouchX = x; 
      mLastTouchY = y; 
      mActivePointerId = ev.getPointerId(0); 
      break; 
     } 

     case MotionEvent.ACTION_MOVE: { 
      final int pointerIndex = ev.findPointerIndex(mActivePointerId); 
      final float x = ev.getX(pointerIndex); 
      final float y = ev.getY(pointerIndex); 

      // Only move if the ScaleGestureDetector isn't processing a gesture. 
      if (!mScaleDetector.isInProgress()) { 
       final float dx = x - mLastTouchX; 
       final float dy = y - mLastTouchY; 

       mPosX += dx; 
       mPosY += dy; 

       invalidate(); 
      } 

      mLastTouchX = x; 
      mLastTouchY = y; 

      break; 
     } 

     case MotionEvent.ACTION_UP: { 
      mActivePointerId = INVALID_POINTER_ID; 
      break; 
     } 

     case MotionEvent.ACTION_CANCEL: { 
      mActivePointerId = INVALID_POINTER_ID; 
      break; 
     } 

     case MotionEvent.ACTION_POINTER_UP: { 
      final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
      final int pointerId = ev.getPointerId(pointerIndex); 
      if (pointerId == mActivePointerId) { 
       // This was our active pointer going up. Choose a new 
       // active pointer and adjust accordingly. 
       final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 
       mLastTouchX = ev.getX(newPointerIndex); 
       mLastTouchY = ev.getY(newPointerIndex); 
       mActivePointerId = ev.getPointerId(newPointerIndex); 
      } 
      break; 
     } 
     } 

     return true; 
    } 

    @Override 
    public void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 

     canvas.save(); 
     Log.d("MapView", "X: " + mPosX + " Y: " + mPosY); 
     canvas.translate(mPosX, mPosY); 
     canvas.scale(mScaleFactor, mScaleFactor); 
     mImage.draw(canvas); 
     canvas.restore(); 
    } 

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 
     @Override 
     public boolean onScale(ScaleGestureDetector detector) { 
      mScaleFactor *= detector.getScaleFactor(); 

      // Don't let the object get too small or too large. 
      mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f)); 

      invalidate(); 
      return true; 
     } 
    } 

} 

여기까지지도가 성공적으로 응용 프로그램에 입력이며, 이동 및 줌이 모두 있습니다.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context=".MapView" > 

    <com.example.drsystem.MapView 
     android:id="@+id/mapView1" 
     android:layout_width="fill_parent" 
     android:layout_height="400dp" 
     android:layout_above="@+id/button2" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentRight="true" 
     android:layout_alignParentTop="true" /> 

... 

</RelativeLayout> 

이 모든 정보를 바탕으로, 어떻게 점을 그릴 수 있으며, 지속적으로 내지도에 위치를 업데이트 다음과 같이

그리고, 나는 레이아웃 XML 파일에이 사용자 정의보기를 삽입?

업데이트 :

문제는 단순히 사용자 지정보기 위에 또 다른 작은 이미지를 넣고 주위를 이동하는 방법에 대한 것입니다.

나는 또한 참조를 위해 여기에 스크린 샷을 첨부

:

enter image description here

버튼과 textviews 위의 영역 내 MapView

+1

는 Redpin의 소스를 확인합니다. 그것은 정확히 – Reno

답변

1

여기는 내가 말한 것을 한 (내 드래그 동작에만 해당) 코드의 일부입니다. 확대/축소는 약간 복잡합니다. 나는 두 손가락의 중간이나 (0.0) 화면에

첫째는 점을 초기하지만 눈에 보이지 않는

ImageButton dot = new ImageButton(this);// since I add onClick for the dot  
//setImageBitmap 
dot.setVisibility(View.INVISIBLE); 
RelativeLayout.LayoutParams dotparams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); 
dotparams.setMargins(0,0,0,0); 
dot.setLayoutParams(dotparams); 
final RelativeLayout myLayout = (RelativeLayout)findViewById(R.id.maplayout);//set an Id for your RelativeLayout 
myLayout.addView(dot,dotparams); 

()에

Bitmap.getWidth()/getHeight에서 얻을 수

dotImageWidth/높이를 매핑 관련 위치에 점을 추가 스위치 전에 onTouchEvent에서

private void displayPositon(int dotx, int doty) { 
    dot.setVisibility(View.VISIBLE); 
    RelativeLayout.LayoutParams dotparams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); 
    dotparams.setMargins((int)(((android.widget.RelativeLayout.LayoutParams) mImage.getLayoutParams()).leftMargin + dotx - dotImageWidth/2),(int)(((android.widget.RelativeLayout.LayoutParams) mImage.getLayoutParams()).topMargin + doty - dotImageHeight),0,0); 
    dot.setLayoutParams(params); 

RelativeLayout.LayoutParams params[]; 
params = new RelativeLayout.LayoutParams[2];//one is the top-left of your mapView, one is the dot 
params[0]= (android.widget.RelativeLayout.LayoutParams) dot.getLayoutParams(); 
params[1]= (android.widget.RelativeLayout.LayoutParams) mImage.getLayoutParams(); 

경우 ACTION_MOVE 경우

dotleftMargin = ((android.widget.RelativeLayout.LayoutParams) dot.getLayoutParams()).leftMargin; 
dottopMargin = ((android.widget.RelativeLayout.LayoutParams) dot.getLayoutParams()).topMargin; 
mapleftMargin = ((android.widget.RelativeLayout.LayoutParams) mImage.getLayoutParams()).leftMargin; 
maptopMargin = ((android.widget.RelativeLayout.LayoutParams) mImage.getLayoutParams()).topMargin; 

Action_Down

params[0].setMargins((int)(x - mLastTouchX + dotleftMargin), (int)(y- mLastTouchY + dottopMargin), 0, 0); 
params[1].setMargins((int)(x - mLastTouchX + mapleftMargin), (int)(y- mLastTouchY + maptopMargin), 0, 0); 
+0

내 질문에 약간 오해 한 것 같아. 제 질문은 실제로지도에 관한 것이 아닙니다. 간단히 말해서 : 다른 이미지 위에 어떻게 이미지를 놓을 수 있습니까? 그에 따라 답변을 수정 해주십시오. 감사. –

+0

나는 ImageView를 ImageView로 변경하고 RelativeLayout에 ID를 추가하고 레이아웃에 이미지를 추가하기 만하면됩니다. 지도를 묶을 수 없기 때문에지도를 이동할 때 쓴 점을 사용하여 점을 이동하는 방법을 썼습니다. – Gina

2

LocationClient API의 (대신을 locationManager의)를 사용하여 시작하려면 Wi-Fi 및 네트워크가 혼합 된 gps 제공 업체와 잘 작동하기 때문입니다. 또한 센서를 사용하여 움직임을 인식하므로 배터리로 절약 할 수 있습니다.

지도에 아이콘을 배치 한 다음 위치 대 조용 대구를 사용합니다. 필요에 맞게 사용자 정의하십시오. 조금 거칠지 만 작동합니다.

private class LocationMarker extends ItemizedOverlay<OverlayItem> { 
    private Activity appContext; 
    private List<OverlayItem> items = new ArrayList<OverlayItem>(); 
    private Drawable marker = null; 
    private OverlayItem inDrag = null; 
    private ImageView dragImage = null; 
    private int xDragImageOffset = 0; 
    private int yDragImageOffset = 0; 
    private int xDragTouchOffset = 0; 
    private int yDragTouchOffset = 0; 
    private MapView location; 
    private boolean pickupOrDrop; 

    public LocationMarker(Activity newAppContext, MapView newLocation, Drawable newMarker, 
      ImageView newPoint, boolean newWhichPoint) { 
     super(newMarker); 
     this.appContext = newAppContext; 
     this.location = newLocation; 
     this.marker = newMarker; 
     this.dragImage = newPoint; 
     this.pickupOrDrop = newWhichPoint; 

     xDragImageOffset = dragImage.getDrawable().getIntrinsicWidth()/2; 
     yDragImageOffset = dragImage.getDrawable().getIntrinsicHeight(); 
     populate(); 
    } 

    public void placeMarker(GeoPoint myPoint) { 
     OverlayItem toDrop = new OverlayItem(myPoint, "", ""); 
     items.add(toDrop); 
     populate(); 
    } 

    @Override 
    protected OverlayItem createItem(int i) { 
     return (items.get(i)); 
    } 

    @Override 
    public void draw(Canvas canvas, MapView mapView, boolean shadow) { 
     super.draw(canvas, mapView, shadow); 
     boundCenterBottom(marker); 
    } 

    @Override 
    public int size() { 
     return (items.size()); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event, MapView mapView) { 
     if (pickupOrDrop != whichPoint) 
      return false; 
     final int action = event.getAction(); 
     final int x = (int) event.getX(); 
     final int y = (int) event.getY(); 
     boolean result = false; 

     // Draw temp image 
     if (action == MotionEvent.ACTION_DOWN) { 
      Log.d("iTaxeeta:Overlay", "Action Down" + marker.toString()); 
      GeoPoint myPoint = null; 
      if (items.isEmpty()) { 
       if (whichPoint == PICKUP) { 
        myPoint = source = location.getProjection().fromPixels(
          x - xDragTouchOffset, y - yDragTouchOffset); 
       } else if (whichPoint == DROP) { 
        myPoint = destination = location.getProjection().fromPixels(
          x - xDragTouchOffset, y - yDragTouchOffset); 
       } 
       OverlayItem toDrop = new OverlayItem(myPoint, "", ""); 
       items.add(toDrop); 
       populate(); 
      } 
      for (OverlayItem item : items) { 
       Point p = new Point(0, 0); 
       Log.d("iTaxeeta:Overlay", item.getTitle()); 
       location.getProjection().toPixels(item.getPoint(), p); 
       if (hitTest(item, marker, x - p.x, y - p.y)) { 
        result = true; 
        inDrag = item; 
        items.remove(inDrag); 
        populate(); 

        xDragTouchOffset = 0; 
        yDragTouchOffset = 0; 
        setDragImagePosition(p.x, p.y); 

        dragImage.setVisibility(View.VISIBLE); 
        xDragTouchOffset = x - p.x; 
        yDragTouchOffset = y - p.y; 

        break; 
       } 
       else { 
        items.clear(); 
        populate(); 
        if (whichPoint == PICKUP) 
         myPoint = source = location.getProjection().fromPixels(
           x - xDragTouchOffset, y - yDragTouchOffset); 
        else if (whichPoint == DROP) 
         myPoint = destination = location.getProjection().fromPixels(
           x - xDragTouchOffset, y - yDragTouchOffset); 
        new GetGeoAddress((IActionBar) appContext, myPoint).execute(); 
        OverlayItem toDrop = new OverlayItem(myPoint, "", ""); 
        items.add(toDrop); 
        populate(); 
        if (source != null && destination != null) { 
         searchCabs.setEnabled(true); 
         // tip.startAnimation(rollUpAnimation); 
         searchCabs.setTextColor(Color.parseColor("#eeeee4")); 
         if (whichPoint == PICKUP) 
          searchCabs.setBackgroundColor(Color.parseColor("#fe000a")); 
         else if (whichPoint == DROP) 
          searchCabs.setBackgroundColor(Color.parseColor("#17ee27")); 
        } 
        break; 
       } 
      } 
     } 
     // Draw temp image while moving finger across the screen 
     else if (action == MotionEvent.ACTION_MOVE && inDrag != null) { 
      Log.d("iTaxeeta:Overlay", "Action Move" + marker.toString()); 
      setDragImagePosition(x, y); 
      result = true; 
     } 
     // Position the selected point now 
     else if (action == MotionEvent.ACTION_UP && inDrag != null) { 
      GeoPoint myPoint = null; 
      Log.d("iTaxeeta:Overlay", "Action Up" + marker.toString()); 
      dragImage.setVisibility(View.VISIBLE); 
      if (whichPoint == PICKUP) 
       myPoint = source = location.getProjection().fromPixels(x - xDragTouchOffset, 
         y - yDragTouchOffset); 
      else if (whichPoint == DROP) 
       myPoint = destination = location.getProjection().fromPixels(
         x - xDragTouchOffset, y - yDragTouchOffset); 
      OverlayItem toDrop = new OverlayItem(myPoint, inDrag.getTitle(), 
        inDrag.getSnippet()); 
      items.add(toDrop); 
      populate(); 
      inDrag = null; 
      new GetGeoAddress((IActionBar) appContext, myPoint).execute(); 
      if (source != null && destination != null) { 
       searchCabs.setEnabled(true); 
       // tip.startAnimation(rollUpAnimation); 
       searchCabs.setTextColor(Color.parseColor("#eeeee4")); 
       if (whichPoint == PICKUP) 
        searchCabs.setBackgroundColor(Color.parseColor("#fe000a")); 
       else if (whichPoint == DROP) 
        searchCabs.setBackgroundColor(Color.parseColor("#17ee27")); 
      } 
      result = true; 

     } 

     return (result || super.onTouchEvent(event, mapView)); 
    } 
+0

답변을 주셔서 감사합니다,하지만 난 실제로 전화로 제공되는 위치 서비스를 사용하지 않을거야. Wi-Fi 나 GPS를 사용하지 않기 때문입니다. 위치를 찾을 수있는 자체 설계 알고리즘이 있습니다. 따라서 질문은 내 사용자 정의보기에 마커를 오버레이하여 필요에 따라 이동하는 방법입니다. –