Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapbox Android SDK - Draggable marker

Tags:

android

mapbox

How to make a marker draggable in the Mapbox Android SDK? Is that even possible?

If not, what other free open map engine support this feature?

Thanks!

like image 831
toan.tran Avatar asked Nov 07 '14 03:11

toan.tran


3 Answers

I had to implement draggable markers for one of my projects. The only solution I found is to extend existing Marker class with mehod checking for drag event and updating marker position accordingly.

package com.example.map;

import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.mapbox.mapboxsdk.api.ILatLng;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.overlay.Marker;
import com.mapbox.mapboxsdk.views.MapView;
import com.mapbox.mapboxsdk.views.util.Projection;

public class DraggableMarker extends Marker {

    private static final String TAG = "map.DraggableMarker";

    private boolean mIsDragged;
    private static final RectF mTempRect = new RectF();
    private static final PointF mTempPoint = new PointF();
    private float mDx, mDy;

    public DraggableMarker(String title, String description, LatLng latLng) {
        super(title, description, latLng);
        mIsDragged = false;
    }

    public DraggableMarker(MapView mv, String aTitle, String aDescription, LatLng aLatLng) {
        super(mv, aTitle, aDescription, aLatLng);
        mIsDragged = false;
    }

    public boolean drag(View v, MotionEvent event) {
        final int action = event.getActionMasked();
        if(action == MotionEvent.ACTION_DOWN) {
            Projection pj = ((MapView)v).getProjection();
            RectF bound = getDrawingBounds(pj, mTempRect);
            if(bound.contains(event.getX(), event.getY())) {
                mIsDragged = true;
                PointF p = getPositionOnScreen(pj, mTempPoint);
                mDx = p.x - event.getX();
                mDy = p.y - event.getY();
            }
        }
        if(mIsDragged) {
            if((action == MotionEvent.ACTION_CANCEL) ||
                    (action == MotionEvent.ACTION_UP)) {
                mIsDragged = false;
            } else {
                Projection pj = ((MapView)v).getProjection();
                ILatLng pos = pj.fromPixels(event.getX() + mDx, event.getY() + mDy);
                setPoint(new LatLng(pos.getLatitude(), pos.getLongitude()));
            }
        }

        return mIsDragged;
    }
}

Later you need to add listener on touch events on MapView and check if your marker (or one of many in your marker collection) is affected by the event.

mMarker = new DraggableMarker(mMapView, "", "", aCenter);
mMarker.setIcon(new Icon(getActivity().getApplicationContext(), Icon.Size.SMALL, "marker-stroked", "FF0000"));
mMapView.addMarker(mMarker);

mMapView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return mMarker.drag(v, event);
    }
});
like image 110
czarles Avatar answered Oct 17 '22 09:10

czarles


I’ve been recently working with mapbox android SDK, where I came across situation of picking up location using marker. So myself created a screen with marker (using image view) at centre . On each camera idle listener you get the get location of centre of screen.

    /**
     * Method to create the location picker icon at the center of screen 
     */
    private void createLocationPickerMarker() {
        ivLocationPicker = new ImageView(this); //Here image view is dynamically created
        ivLocationPicker.setImageResource(R.drawable.ic_location_picker); //reference to the drawable image
        // Statically Set drop pin in center of screen
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 
        ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER); //image parameters are sent and set at the center
        float density = getResources().getDisplayMetrics().density; //get screen density 
        params.bottomMargin = (int) (12 * density); //inorder to place bottom tip at the center bottom margin added - here 12 is multiplied with the screen density and added as bottom margin as this will be mostly at the centre (based on average value of all density location_picker image height)
        ivLocationPicker.setLayoutParams(params); //parameters are set to the image
        mapView.addView(ivLocationPicker); //image is added to the map
    }

    /**
     * Method to pick location from marker
     */
    private LatLng getLatLngFromMarker() {
        return mapboxMap.getProjection().fromScreenLocation(new PointF(ivLocationPicker.getLeft() + (ivLocationPicker.getWidth() / 2), ivLocationPicker.getBottom()));
    }

    @Override
    public void onMapReady(MapboxMap mapboxMap) {
        pickedLatLng = getLatLngFromMarker(); // used to pick lat lng while coming to screen
        mapboxMap.addOnCameraIdleListener(() -> { //listener for on camera idle change
            pickedLatLng = getLatLngFromMarker();
        });
    }
like image 1
Raj Avatar answered Oct 17 '22 10:10

Raj


You can use annotation plugin for Mapbox. One of the implementation is in this repo https://github.com/everestkid/editablepolygon

like image 1
everestkid Avatar answered Oct 17 '22 09:10

everestkid