2013-07-05 15 views
11

Obecnie rozwijam system śledzenia, aby wykreślić trajektorię ruchu użytkownika wewnątrz pomieszczenia lub co innego.Jak narysować mały obraz znacznika i dalej odświeżać jego pozycję na moim obrazie mapy CUSTOM? - Android

Teraz udało mi się zaimportować mapę do aplikacji, a mapę można powiększać i przenosić. Następnym krokiem jest umieszczenie znacznika, który wskaże lokalizację użytkownika na mapie i przesunie znacznik wokół OVER na mapie. (jak unoszący się na mapie)

Przeczytałem go gdzieś i wydaje mi się, że można to zrobić za pomocą MyLocationOverlay, ale większość przykładów online to zastosowanie go do google map. Jednak w moim przypadku moja mapa nie jest google map, jest to moja mapa OWN. (Mapa może być mapą mojego pokoju lub nawet mapą, którą sam rysuję!)

Wykonałem algorytm śledzenia, tj. Wiem, gdzie umieścić mój obraz znacznika.

Tak więc pozostaje tylko pytanie, jak przedstawić obraz znacznika na obrazie mapy.

W szczegółach, mam własny pogląd, MapView zdefiniowane w następujący sposób:

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; 
     } 
    } 

} 

Maksymalnie tutaj, mapa jest z powodzeniem wprowadzane do aplikacji, i to zarówno ruchomy i zoomable.

A potem wstawić ten widok niestandardowy do pliku XML układu następująco:

<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> 

Na podstawie wszystkich tych informacji, w jaki sposób mogę narysować kropkę i stale aktualizować swoją pozycję na mojej mapie?

Aktualizacja:

Pytanie jest po prostu o oddanie kolejny mały obraz na szczycie widoku niestandardowym i przesuwając go dookoła.

ja również dołączyć tutaj zrzut ekranu w celach:

enter image description here

Obszar nad przyciskami i TextView Is My MapView

+1

Sprawdź źródło Redpin. Dokładnie to robi – Reno

Odpowiedz

1

Oto część mojego kodu, który zrobił to, o co prosisz (ale tylko dla gestów przeciągania), powiększanie jest nieco skomplikowane. Muszę wiedzieć, na którym punkcie twoje powiększanie bazuje, na przykład na środku dwóch palców lub na (0.0) na ekranie

pierwsze litery kropkę ale niewidoczny

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); 

za dodać kropkę z odpowiednią pozycję do map

dotImageWidth/wysokość może dostać od Bitmap.getWidth()/getHeight()

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); 

w onTouchEvent przed przełącznikiem

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(); 

przypadek Action_Down

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; 

przypadek ACTION_MOVE

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

Myślę, że źle zrozumiałeś moje pytanie. Moje pytanie nie dotyczy właściwie mapy. Po prostu: jak mogę umieścić obraz na innym obrazie? Czy mógłbyś odpowiednio zmodyfikować swoją odpowiedź? Dzięki. –

+0

JESTEM odpowiedzieć na twoje pytanie po prostu zmienić ImageButton na ImageView i dodać identyfikator w RelativeLayout i dodać obraz na układ. Nie mogę powiązać mapy i kropki, więc napisałem, kiedy przenosisz mapę, jak zmienić swoją kropkę – Gina

2

Aby rozpocząć, należy LocationClient API (zamiast LocationManager) ponieważ działają bardzo dobrze z mieszanym dostawcą GPS i siecią. Używają również czujników, aby rozpoznać ruch, aby zaoszczędzić na baterii.

Używam następującego kodu LocationOverlay umieszczającego moje ikony na mapie. Dostosuj go do swoich potrzeb. Jest nieco szorstki, ale działa.

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

Dziękuję za odpowiedź, ale tak naprawdę nie zamierzam korzystać z usługi lokalizacji zapewnianej przez telefon. Ponieważ nie używam Wi-Fi ani GPS. Mam własny algorytm, aby znaleźć lokalizację. Pytanie brzmi po prostu, jak nakładać znacznik na moim widoku niestandardowym i przenosić go w razie potrzeby. –

Powiązane problemy