Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,12 @@ class RNMBXPointAnnotation(private val mContext: Context, private val mManager:
}
}

val isDraggable: Boolean
get() = mDraggable

fun setDraggable(draggable: Boolean) {
// Mapbox isDraggable stays false (set in makeMarker)
mDraggable = draggable
annotation?.let { annotation ->
annotation.isDraggable = draggable
pointAnnotations?.update(annotation)
}
}

fun setReactSelected(selected: Boolean) {
Expand Down Expand Up @@ -239,7 +239,8 @@ class RNMBXPointAnnotation(private val mContext: Context, private val mManager:
val options = mCoordinate?.let {
PointAnnotationOptions()
.withPoint(it)
.withDraggable(mDraggable)
// SDK drag is disabled, long-press drag is handled by RNMBXPointAnnotationCoordinator
.withDraggable(false)
.withIconSize(1.0)
.withSymbolSortKey(10.0)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
package com.rnmapbox.rnmbx.components.annotation

import com.mapbox.maps.MapView
import com.mapbox.maps.plugin.annotation.Annotation
import com.mapbox.maps.ScreenCoordinate
import com.mapbox.maps.plugin.annotation.AnnotationConfig
import com.mapbox.maps.plugin.annotation.annotations
import com.mapbox.maps.plugin.annotation.generated.OnPointAnnotationClickListener
import com.mapbox.maps.plugin.annotation.generated.OnPointAnnotationDragListener
import com.mapbox.maps.plugin.annotation.generated.PointAnnotation
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationManager
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationOptions
import com.mapbox.maps.plugin.annotation.generated.createPointAnnotationManager
import com.rnmapbox.rnmbx.components.annotation.RNMBXPointAnnotation
import com.rnmapbox.rnmbx.utils.Logger

class RNMBXPointAnnotationCoordinator(val mapView: MapView, layerId: String? = "RNMBX-mapview-annotations") {
val manager: PointAnnotationManager;
var annotationClicked = false
var annotationDragged = false

var selected: RNMBXPointAnnotation? = null

private var draggedAnnotation: RNMBXPointAnnotation? = null

val annotations: MutableMap<String, RNMBXPointAnnotation> = hashMapOf()
val callouts: MutableMap<String, RNMBXPointAnnotation> = hashMapOf()

val isDragging: Boolean
get() = draggedAnnotation != null

init {
manager = if (layerId != null) {
mapView.annotations.createPointAnnotationManager(AnnotationConfig(layerId = layerId))
Expand All @@ -33,45 +35,6 @@ class RNMBXPointAnnotationCoordinator(val mapView: MapView, layerId: String? = "
onAnnotationClick(pointAnnotation)
false
})
manager.addDragListener(object : OnPointAnnotationDragListener {
override fun onAnnotationDragStarted(_annotation: Annotation<*>) {
annotationDragged = true;
var reactAnnotation: RNMBXPointAnnotation? = null
for (key in annotations.keys) {
val annotation = annotations[key]
val curMarkerID = annotation?.mapboxID
if (_annotation.id == curMarkerID) {
reactAnnotation = annotation
}
}
reactAnnotation?.let { it.onDragStart() }
}

override fun onAnnotationDrag(_annotation: Annotation<*>) {
var reactAnnotation: RNMBXPointAnnotation? = null
for (key in annotations.keys) {
val annotation = annotations[key]
val curMarkerID = annotation?.mapboxID
if (_annotation.id == curMarkerID) {
reactAnnotation = annotation
}
}
reactAnnotation?.let { it.onDrag() }
}

override fun onAnnotationDragFinished(_annotation: Annotation<*>) {
annotationDragged = false;
var reactAnnotation: RNMBXPointAnnotation? = null
for (key in annotations.keys) {
val annotation = annotations[key]
val curMarkerID = annotation?.mapboxID
if (_annotation.id == curMarkerID) {
reactAnnotation = annotation
}
}
reactAnnotation?.let { it.onDragEnd() }
}
})
}

fun getAndClearAnnotationClicked(): Boolean {
Expand All @@ -82,12 +45,38 @@ class RNMBXPointAnnotationCoordinator(val mapView: MapView, layerId: String? = "
return false
}

fun getAndClearAnnotationDragged(): Boolean {
if (annotationDragged) {
annotationDragged = false
/**
* Starts a custom long-press drag if a draggable RN PointAnnotation is under [screenCoordinate].
* Mapbox SDK drag is disabled; this mirrors iOS UILongPress-driven dragging.
*/
fun handleLongPress(screenCoordinate: ScreenCoordinate): Boolean {
if (draggedAnnotation != null) {
return true
}
return false
val pointAnnotation = manager.queryMapForFeatures(screenCoordinate) ?: return false
val reactAnnotation = lookupForClick(pointAnnotation) ?: return false
if (!reactAnnotation.isDraggable) {
return false
}
draggedAnnotation = reactAnnotation
reactAnnotation.onDragStart()
return true
}

fun handleDragMove(screenCoordinate: ScreenCoordinate): Boolean {
val reactAnnotation = draggedAnnotation ?: return false
val mapboxMap = mapView.mapboxMap
val point = mapboxMap.coordinateForPixel(screenCoordinate)
reactAnnotation.setCoordinate(point)
reactAnnotation.onDrag()
return true
}

fun handleDragEnd(): Boolean {
val reactAnnotation = draggedAnnotation ?: return false
draggedAnnotation = null
reactAnnotation.onDragEnd()
return true
}

fun lookupForClick(point: PointAnnotation): RNMBXPointAnnotation? {
Expand Down Expand Up @@ -146,6 +135,9 @@ class RNMBXPointAnnotationCoordinator(val mapView: MapView, layerId: String? = "
if (annotation == selected) {
selected = null
}
if (annotation == draggedAnnotation) {
draggedAnnotation = null
}
annotations.remove(annotation.iD)
}

Expand All @@ -166,6 +158,7 @@ class RNMBXPointAnnotationCoordinator(val mapView: MapView, layerId: String? = "
}

fun destroy() {
draggedAnnotation = null
mapView.annotations.removeAnnotationManager(manager)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.graphics.BitmapFactory
import android.os.Handler
import android.os.Looper
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.View.OnLayoutChangeListener
import android.view.ViewGroup
Expand Down Expand Up @@ -310,14 +311,27 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie

gesturesPlugin.addOnMoveListener(object : OnMoveListener {
override fun onMoveBegin(moveGestureDetector: MoveGestureDetector) {
if (pointAnnotationCoordinators.any { it.isDragging }) {
return
}
mapGestureBegin(MapGestureType.Move, moveGestureDetector)
}

override fun onMove(moveGestureDetector: MoveGestureDetector): Boolean {
val focalPoint = ScreenCoordinate(
moveGestureDetector.focalPoint.x.toDouble(),
moveGestureDetector.focalPoint.y.toDouble()
)
if (pointAnnotationCoordinators.any { it.handleDragMove(focalPoint) }) {
return true
}
return mapGesture(MapGestureType.Move, moveGestureDetector)
}

override fun onMoveEnd(moveGestureDetector: MoveGestureDetector) {
if (pointAnnotationCoordinators.any { it.handleDragEnd() }) {
return
}
mapGestureEnd(MapGestureType.Move, moveGestureDetector)
}
})
Expand Down Expand Up @@ -776,17 +790,14 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie
}

override fun onMapLongClick(point: Point): Boolean {
val _this = this
if (pointAnnotationCoordinators.any { it.getAndClearAnnotationDragged() }) {
val screenPointPx = mMap?.pixelForCoordinate(point) ?: return false
// Long-press on a draggable PointAnnotation starts custom drag (iOS parity)
if (pointAnnotationCoordinators.any { it.handleLongPress(screenPointPx) }) {
return true
}
val screenPointPx = mMap?.pixelForCoordinate(point)
if (screenPointPx != null) {
val screenPointDp = toDp(screenPointPx)
val event = MapClickEvent(_this, LatLng(point), screenPointDp, EventTypes.MAP_LONG_CLICK)
mManager.handleEvent(event)
}

val screenPointDp = toDp(screenPointPx)
val event = MapClickEvent(this, LatLng(point), screenPointDp, EventTypes.MAP_LONG_CLICK)
mManager.handleEvent(event)
return false
}

Expand Down Expand Up @@ -1277,6 +1288,7 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie
mapView.setLayoutParams(matchParent)
addView(mapView)
}
installMapTouchListener()
this.addOnLayoutChangeListener(this)

val map = mapView.getMapboxMap()
Expand Down Expand Up @@ -1620,27 +1632,35 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie
// endregion
}

// region requestDisallowInterceptTouchEvent
fun RNMBXMapView.updateRequestDisallowInterceptTouchEvent(oldValue: Boolean, value: Boolean) {
if (oldValue == value) {
return
}
if (value) {
withMapView {
it.setOnTouchListener { view, event ->
// region map touch (PointAnnotation drag + requestDisallowInterceptTouchEvent)
fun RNMBXMapView.installMapTouchListener() {
withMapView { map ->
map.setOnTouchListener { _, event ->
when (event.actionMasked) {
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
// End long-press drag even when the finger lifts without a move gesture
pointAnnotationCoordinators.any { it.handleDragEnd() }
}
}
if (requestDisallowInterceptTouchEvent) {
// Preserve pre-drag behavior: disallow parent intercept, forward, consume
this.requestDisallowInterceptTouchEvent(true)
mapView.onTouchEvent(event)
map.onTouchEvent(event)
true
} else {
// Observe only, do not consume or manually forward
false
}
}
} else {
withMapView {
it.setOnTouchListener { view, event ->
mapView.onTouchEvent(event)
}
}
}
}

fun RNMBXMapView.updateRequestDisallowInterceptTouchEvent(oldValue: Boolean, value: Boolean) {
if (oldValue == value) {
return
}
installMapTouchListener()
}
// endregion


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.react.viewmanagers.RNMBXFillLayerManagerInterface
import com.facebook.react.uimanager.ViewManagerDelegate
import com.facebook.react.viewmanagers.RNMBXFillLayerManagerDelegate
import com.rnmapbox.rnmbx.utils.extensions.asStringOrNull

class RNMBXFillLayerManager : ViewGroupManager<RNMBXFillLayer>(),
RNMBXFillLayerManagerInterface<RNMBXFillLayer> {
Expand Down Expand Up @@ -40,12 +41,12 @@ class RNMBXFillLayerManager : ViewGroupManager<RNMBXFillLayer>(),

@ReactProp(name = "aboveLayerID")
override fun setAboveLayerID(layer: RNMBXFillLayer, aboveLayerID: Dynamic) {
layer.setAboveLayerID(aboveLayerID.asString())
layer.setAboveLayerID(aboveLayerID.asStringOrNull())
}

@ReactProp(name = "belowLayerID")
override fun setBelowLayerID(layer: RNMBXFillLayer, belowLayerID: Dynamic) {
layer.setBelowLayerID(belowLayerID.asString())
layer.setBelowLayerID(belowLayerID.asStringOrNull())
}

@ReactProp(name = "layerIndex")
Expand Down
1 change: 1 addition & 0 deletions docs/PointAnnotation.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Manually selects/deselects annotation
boolean
```
Enable or disable dragging. Defaults to false.
When enabled, a long press is required to begin dragging (iOS and Android).

_defaults to:_ `false`

Expand Down
2 changes: 1 addition & 1 deletion docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -6454,7 +6454,7 @@
"required": false,
"type": "boolean",
"default": "false",
"description": "Enable or disable dragging. Defaults to false."
"description": "Enable or disable dragging. Defaults to false.\nWhen enabled, a long press is required to begin dragging (iOS and Android)."
},
{
"name": "coordinate",
Expand Down
1 change: 1 addition & 0 deletions src/components/PointAnnotation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type Props = BaseProps & {

/**
* Enable or disable dragging. Defaults to false.
* When enabled, a long press is required to begin dragging (iOS and Android).
*/
draggable?: boolean;

Expand Down