12

現在、部屋の中などでのユーザーの移動軌跡をプロットする追跡システムを開発しています。

これで、マップをアプリにインポートすることができました。マップは自由にズームおよび移動できます。次のステップは、マップ上にユーザーの位置を示すマーカーを配置し、マップ上でマークを移動することです。(地図上に浮かんでいるように)

私はそれをどこかで読んで、これは で行われる可能性があると思いますがMyLocationOverlay、オンラインの例のほとんどはすべてgoogle map. ただし、私の場合、 my map は ではなくgoogle mapmy OWN mapです。(地図は自分の部屋の地図でもいいですし、自分で描いた地図でも構いません!)

追跡アルゴリズムを実行しました。つまり、マーカー画像を配置する場所を知っています

したがって、唯一の問題は、マップ イメージの上にマーカー イメージを表示する方法です。

詳細には、次のような自己定義ビュー MapView があります。

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

}

ここまでで、地図はアプリに正常に入力され、移動とズームが可能になりました。

次に、このカスタム ビューを次のようにレイアウト XML ファイルに挿入します。

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

このすべての情報に基づいて、どうすればドットを描画し、マップ上のその位置を常に更新できますか?

アップデート:

問題は、カスタム ビューの上に別の小さな画像を配置して移動することです。

また、参考のためにスクリーンショットをここに添付します。

ここに画像の説明を入力

ボタンとテキストビューの上の領域は私のMapView

4

2 に答える 2

2

まず、(LocationManager の代わりに) LocationClient API を使用します。これらの API は、混合 GPS プロバイダーの wifi とネットワークで非常にうまく機能するためです。また、センサーを使用して動きを認識し、バッテリーを節約できます。

次の LocationOverlay タラを使用して、アイコンをマップに配置します。必要に応じてカスタマイズしてください。少し荒いですが、機能します。

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));
    }
于 2013-07-05T06:11:05.607 に答える
1

これは、あなたが求めたことを実行した私のコードの一部です(ただし、ドラッグジェスチャのみ)。ズームは少し複雑です。たとえば、2 本の指の中央または画面上の (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);

関連する位置にドットをマップに追加する

dotImageWidth/Height は 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);

スイッチの前の onTouchEvent で

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

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

ケース 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);
于 2013-07-05T07:06:06.623 に答える