mapbox / mapbox-gl-native

Interactive, thoroughly customizable maps in native Android, iOS, macOS, Node.js, and Qt applications, powered by vector tiles and OpenGL
https://mapbox.com/mobile
Other
4.37k stars 1.33k forks source link

Add Draggable Markers #2450

Closed tobrun closed 5 years ago

tobrun commented 9 years ago

Google Maps allows its Markers to be draggable and allows end developers to register to events

pshustad commented 8 years ago

A workaround would at least be to provide a MapView.OnMoveListener with a onMove callback. The callback would typically be called if the view detecs a MotionEvent.ACTION_MOVE event and the event is not dispatched as a scroll event. This happens e.g. after a long-press followed by a drag.

We are currently working on an Android Map Editor using mapbox-gl-native as the framework. However, I see no possibilities for detecting when the user tries to move a marker. With the above workaround we could detect a long-press followed by a move event and then move the marker by recreating it in the new position.

ljbade commented 8 years ago

@pshustad It is possible to add your own onTouch listener to MapView from an activity since it inherits that from View.

We used this as a work around to detect long presses until we had a chance to add a long press listener.

pshustad commented 8 years ago

@ljbade Thanks for the advice. I was actually in the middle of preparing a pull request for a full-blown implementation of the OnMarkerDragListener API, but might try this workaround instead.

Of course, if there are future plans for a Mapbox "drag marker" API, I would be happy to continue working on it.

ljbade commented 8 years ago

@pshustad feel free to keep working on a PR if you want. I just wanted to let you know about the work around.

tobrun commented 8 years ago

Now that #3276 has landed this feature can be implemented using View Markers instead of GL Markers

p-fischer commented 8 years ago

Hi @tobrun , could you please elaborate how you would realize draggable markers with marker views? (I was looking for a possibility to add a touch listener to a marker view but could not find any.)

filipc commented 8 years ago

I'm also interested how to drag Markers same way as it is possible in Google Maps. @tobrun please give us some suggestions or code snippet how you thought to implement it using View Markers. What are the development plans in this area?

tobrun commented 8 years ago

@p-fischer @filipc at this point I haven't started to think about the actual implementation or haven't discussed this internally. This feature just barely didn't make the cut for the 4.1.0 feature list and was considered a nice to have. @frederoni is working on the iOS equivalent in https://github.com/mapbox/mapbox-gl-native/pull/5373.

Ideally I would love to support the multi window drag/drop functionality as shown at Google I/O this year. This will require us to use the Android SDK drag and drop and not create something custom from scratch. At this point, when a drag starts we probably need to call removeMarker and re-add it again when we drop the marker.

DavidMont commented 8 years ago

I hope this will become sooner, My legacy mapbox android have draggable marker, I dont want to change/remove it from this current mapbox sdk

BharathMG commented 8 years ago

@tobrun @ljbade Is there any documentation or experiment PR on how to implement Draggable Marker using ACTION_MOVE touch event? I used to extend ItemizedIconOverlay and override onDrawItem to achieve this in 0.7.4. Any help will be much appreciated! Thanks :)

tobrun commented 8 years ago

This issue is blocked by #5639, that PR will move the touch logic in core instead of the Android binding. This will introduce the requirement of implementing draggable markers in a different way as initially indicated in https://github.com/mapbox/mapbox-gl-native/issues/2450#issuecomment-228201350.

Current thinking:

samucs commented 8 years ago

It is almost 1AM here and I am spending hours trying to find a way to drag a marker. My current application uses the JavaScript flavour and dragging works quite well. However, there is a demand for native Android app and it's being hard to get it implemented. Hope this get some priority in your team, thank you!

tobrun commented 8 years ago

This is on my todo list for improvements to MarkerViews. Currently working on zIndex, this will be the next item on the list.

samucs commented 8 years ago

Hi, any update on this issue? Regards.

marvinernst commented 8 years ago

+1

vanshg commented 7 years ago

One kinda hacky way that I've found of doing this is to use reflection and set an onTouch listener for the MapView. I think this might interfere with the onClick for Markers, but I haven't tested. Furthermore, this behavior does not wait for a long press to start dragging (this is the behavior I wanted, but it may not be appropriate for all cases)

mapView.setOnTouchListener(new View.OnTouchListener() {
            //This onTouch code is a copy of the MapView#onSingleTapConfirmed code, except I'm dragging instead of clicking, and it's being called for every touch event rather than just a tap
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event != null) {
                    PointF tapPoint = new PointF(event.getX(), event.getY());
                    float toleranceSides = 4 * screenDensity;
                    float toleranceTopBottom = 10 * screenDensity;
                    float averageIconWidth = 42;
                    float averageIconHeight = 42;
                    RectF tapRect = new RectF((tapPoint.x - averageIconWidth / 2 - toleranceSides) / screenDensity,
                            (tapPoint.y - averageIconHeight / 2 - toleranceTopBottom) / screenDensity,
                            (tapPoint.x + averageIconWidth / 2 + toleranceSides) / screenDensity,
                            (tapPoint.y + averageIconHeight / 2 + toleranceTopBottom) / screenDensity);
                    try {
                        Method method = mapView.getClass().getDeclaredMethod("getMarkersInRect", RectF.class); //Using reflection to access a Mapbox Package Private method
                        method.setAccessible(true);
                        List<Marker> nearbyMarkers = (List<Marker>) method.invoke(mapView, tapRect);
                        long newSelectedMarkerId = -1;
                        List<Marker> selectedMarkers = map.getSelectedMarkers();
                        if (nearbyMarkers != null && nearbyMarkers.size() > 0) {
                            Collections.sort(nearbyMarkers);
                            for (Marker nearbyMarker : nearbyMarkers) {
                                boolean found = false;
                                for (Marker selectedMarker : selectedMarkers) {
                                    if (selectedMarker.equals(nearbyMarker)) {
                                        found = true;
                                    }
                                }
                                if (!found) {
                                    newSelectedMarkerId = nearbyMarker.getId();
                                    break;
                                }
                            }
                        }

                        if (newSelectedMarkerId >= 0) {
                            List<Annotation> annotations = map.getAnnotations();
                            int count = annotations.size();
                            for (int i = 0; i < count; i++) {
                                Annotation annotation = annotations.get(i);
                                if (annotation instanceof MarkerView) {
                                    if (annotation.getId() == newSelectedMarkerId) {
                                        if (selectedMarkers.isEmpty() || !selectedMarkers.contains(annotation)) {
                                            //DRAG! instead of clicking
                                            annotation.setPosition(map.getProjection().fromScreenLocation(tapPoint));
                                            return true;
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
                return false;
            }
        });
vanshg commented 7 years ago

@tobrun Any plans to have draggable markers in 5.0?

codebee commented 6 years ago

Hi, Any update on for the draggable marker feature? Thanks :)

Meerz commented 6 years ago

Android : any update or trick we use drag marker or point or polyline on map??? i am stuck for four three days on drag marker or point on polyline??? kindly help me to solve out this problem or code??

vanshg commented 6 years ago

@Meerz Refer to the code I posted a few comments above. I can confirm it is still working on Mapbox 6.0.1

@tobrun Is this feature in any future roadmap?

Meerz commented 6 years ago

@vanshg thansk for quick reply i implement but here map.getSelectedMarkers(); and screenDensity cannot resolve??map not resolve annotation.setPosition(map. this also

vanshg commented 6 years ago

@Meerz You will need to adjust the code I posted to match what you've named your variables. In this case, map refers to the MapboxMap instance. You can set screenDensity equal to getResources().getDisplayMetrics().density;

Also, I believe I spoke too soon. The code I posted earlier may need a couple other modifications to work. You should be able to get rid of reflection and get rid of the try-catch (replace the reflection code with List<MarkerView> nearbyMarkers = map.getMarkerViewsInRect(tapRect);

tobrun commented 6 years ago

@vanshg yes, this is going to be implemented when we revamp the annotations api.

atul-anand commented 6 years ago

@tobrun Have you decided on the tentative release date after revamping the annotation api?

Meerz commented 6 years ago

@tobrun any upadates regarding draggable marker???

tobrun commented 6 years ago

An example how to do this with SymbolLayer in #12326

LukasPaczos commented 5 years ago

Draggable markers, and annotations in general, support has been added to the Annotation Plugin in the v0.3.0, see https://github.com/mapbox/mapbox-plugins-android/pull/753.

Feel free to check out the plugin and let us know what you think, thanks!

/cc @chloekraw

tobrun commented 5 years ago

Annotations are deprecated and are replaced by the annotations plugin. Support for dragging annotations is already implemented.