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!
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);
}
});
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();
});
}
You can use annotation plugin for Mapbox. One of the implementation is in this repo https://github.com/everestkid/editablepolygon
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With