Подтвердить что ты не робот

Как нарисовать маленькое изображение маркера и продолжить обновлять его положение на моем изображении карты CUSTOM? - Android

В настоящее время я разрабатываю систему отслеживания для построения траектории движения пользователя внутри комнаты или whaterever.

Теперь мне удалось импортировать мою карту в приложение, и карта может быть увеличена и перемещена. Следующий шаг - поместить маркер, чтобы указать местоположение пользователя на карте и переместить отметку вокруг карты. (например, плавание на карте)

Я прочитал его где-нибудь и думаю, что это может быть сделано с помощью MyLocationOverlay, но большинство примеров в Интернете - все, чтобы применить его к google map. Однако в моем случае моя карта не google 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>

Основываясь на всей этой информации, как я могу нарисовать точку и постоянно обновлять ее положение на моей карте?

Update:

Вопрос только в том, чтобы поместить еще одно маленькое изображение поверх пользовательского представления и перемещать его.

Я также прикладываю скриншот здесь для справки:

enter image description here

Площадь над кнопками и текстовыми окнами - это мой MapView

4b9b3361

Ответ 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);

для добавления точки с соответствующей позицией для отображения

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;

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

Ответ 2

Для начала используйте API LocationClient (вместо LocationManager), так как они отлично работают со смешанными поставщиками Wi-Fi и сетью. Они также используют датчики для распознавания движения, чтобы они могли экономить на аккумуляторе.

Я использую следующую команду 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));
    }