@maplibre/maplibre-react-native 11.0.0-beta.1 → 11.0.0-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/android/src/main/java/org/maplibre/reactnative/components/annotations/markerview/MLRNMarkerView.kt +2 -1
  2. package/android/src/main/java/org/maplibre/reactnative/components/annotations/markerview/MLRNMarkerViewContent.kt +9 -14
  3. package/android/src/main/java/org/maplibre/reactnative/components/annotations/markerview/MarkerViewManager.kt +16 -12
  4. package/android/src/main/java/org/maplibre/reactnative/components/annotations/pointannotation/MLRNPointAnnotation.kt +40 -24
  5. package/android/src/main/java/org/maplibre/reactnative/components/annotations/pointannotation/MLRNPointAnnotationManager.kt +2 -1
  6. package/android/src/main/java/org/maplibre/reactnative/components/mapview/MLRNMapView.kt +49 -88
  7. package/ios/components/annotations/point-annotation/MLRNPointAnnotation.m +23 -2
  8. package/ios/components/annotations/point-annotation/MLRNPointAnnotationComponentView.mm +3 -13
  9. package/ios/components/camera/MLRNCameraComponentView.mm +5 -4
  10. package/ios/components/layer/MLRNLayerComponentView.mm +12 -9
  11. package/ios/components/map-view/MLRNMapView.h +1 -0
  12. package/ios/components/map-view/MLRNMapView.m +30 -11
  13. package/ios/components/map-view/MLRNMapViewComponentView.mm +1 -3
  14. package/ios/components/map-view/MLRNMapViewModule.mm +1 -1
  15. package/ios/components/sources/image-source/MLRNImageSourceComponentView.mm +1 -1
  16. package/ios/components/sources/tile-sources/raster-source/MLRNRasterSourceComponentView.mm +2 -3
  17. package/ios/components/sources/tile-sources/vector-source/MLRNVectorSourceComponentView.mm +2 -3
  18. package/lib/commonjs/components/annotations/LayerAnnotation.js +4 -1
  19. package/lib/commonjs/components/annotations/LayerAnnotation.js.map +1 -1
  20. package/lib/commonjs/components/annotations/marker/Marker.js +0 -5
  21. package/lib/commonjs/components/annotations/marker/Marker.js.map +1 -1
  22. package/lib/commonjs/components/annotations/marker/MarkerViewNativeComponent.ts +2 -2
  23. package/lib/commonjs/components/annotations/view-annotation/PointAnnotationNativeComponent.ts +2 -2
  24. package/lib/commonjs/components/annotations/view-annotation/ViewAnnotation.js +10 -14
  25. package/lib/commonjs/components/annotations/view-annotation/ViewAnnotation.js.map +1 -1
  26. package/lib/commonjs/components/layer/Layer.js +17 -62
  27. package/lib/commonjs/components/layer/Layer.js.map +1 -1
  28. package/lib/commonjs/components/map/Map.js.map +1 -1
  29. package/lib/commonjs/components/user-location/UserLocation.js +21 -12
  30. package/lib/commonjs/components/user-location/UserLocation.js.map +1 -1
  31. package/lib/commonjs/components/user-location/UserLocationPuck.js +16 -16
  32. package/lib/commonjs/components/user-location/UserLocationPuck.js.map +1 -1
  33. package/lib/commonjs/components/user-location/UserLocationPuckHeading.js +8 -10
  34. package/lib/commonjs/components/user-location/UserLocationPuckHeading.js.map +1 -1
  35. package/lib/commonjs/index.js.map +1 -1
  36. package/lib/commonjs/utils/animated/AbstractAnimatedCoordinates.js +11 -5
  37. package/lib/commonjs/utils/animated/AbstractAnimatedCoordinates.js.map +1 -1
  38. package/lib/commonjs/utils/animated/Animated.js +2 -2
  39. package/lib/commonjs/utils/animated/Animated.js.map +1 -1
  40. package/lib/commonjs/utils/animated/AnimatedCoordinatesArray.js +3 -3
  41. package/lib/commonjs/utils/animated/AnimatedCoordinatesArray.js.map +1 -1
  42. package/lib/commonjs/utils/animated/AnimatedExtractCoordinateFromArray.js +6 -7
  43. package/lib/commonjs/utils/animated/AnimatedExtractCoordinateFromArray.js.map +1 -1
  44. package/lib/commonjs/utils/animated/AnimatedGeoJSON.js +17 -17
  45. package/lib/commonjs/utils/animated/AnimatedGeoJSON.js.map +1 -1
  46. package/lib/commonjs/utils/animated/AnimatedPoint.js +48 -42
  47. package/lib/commonjs/utils/animated/AnimatedPoint.js.map +1 -1
  48. package/lib/commonjs/utils/animated/AnimatedRouteCoordinatesArray.js.map +1 -1
  49. package/lib/module/components/annotations/LayerAnnotation.js +4 -1
  50. package/lib/module/components/annotations/LayerAnnotation.js.map +1 -1
  51. package/lib/module/components/annotations/marker/Marker.js +0 -5
  52. package/lib/module/components/annotations/marker/Marker.js.map +1 -1
  53. package/lib/module/components/annotations/marker/MarkerViewNativeComponent.ts +2 -2
  54. package/lib/module/components/annotations/view-annotation/PointAnnotationNativeComponent.ts +2 -2
  55. package/lib/module/components/annotations/view-annotation/ViewAnnotation.js +10 -15
  56. package/lib/module/components/annotations/view-annotation/ViewAnnotation.js.map +1 -1
  57. package/lib/module/components/layer/Layer.js +17 -62
  58. package/lib/module/components/layer/Layer.js.map +1 -1
  59. package/lib/module/components/map/Map.js.map +1 -1
  60. package/lib/module/components/user-location/UserLocation.js +21 -13
  61. package/lib/module/components/user-location/UserLocation.js.map +1 -1
  62. package/lib/module/components/user-location/UserLocationPuck.js +16 -16
  63. package/lib/module/components/user-location/UserLocationPuck.js.map +1 -1
  64. package/lib/module/components/user-location/UserLocationPuckHeading.js +8 -9
  65. package/lib/module/components/user-location/UserLocationPuckHeading.js.map +1 -1
  66. package/lib/module/index.js.map +1 -1
  67. package/lib/module/utils/animated/AbstractAnimatedCoordinates.js +11 -5
  68. package/lib/module/utils/animated/AbstractAnimatedCoordinates.js.map +1 -1
  69. package/lib/module/utils/animated/Animated.js +2 -2
  70. package/lib/module/utils/animated/Animated.js.map +1 -1
  71. package/lib/module/utils/animated/AnimatedCoordinatesArray.js +3 -3
  72. package/lib/module/utils/animated/AnimatedCoordinatesArray.js.map +1 -1
  73. package/lib/module/utils/animated/AnimatedExtractCoordinateFromArray.js +6 -7
  74. package/lib/module/utils/animated/AnimatedExtractCoordinateFromArray.js.map +1 -1
  75. package/lib/module/utils/animated/AnimatedGeoJSON.js +17 -17
  76. package/lib/module/utils/animated/AnimatedGeoJSON.js.map +1 -1
  77. package/lib/module/utils/animated/AnimatedPoint.js +48 -42
  78. package/lib/module/utils/animated/AnimatedPoint.js.map +1 -1
  79. package/lib/module/utils/animated/AnimatedRouteCoordinatesArray.js.map +1 -1
  80. package/lib/typescript/commonjs/src/components/annotations/marker/Marker.d.ts +9 -4
  81. package/lib/typescript/commonjs/src/components/annotations/marker/Marker.d.ts.map +1 -1
  82. package/lib/typescript/commonjs/src/components/annotations/marker/MarkerViewNativeComponent.d.ts +2 -2
  83. package/lib/typescript/commonjs/src/components/annotations/marker/MarkerViewNativeComponent.d.ts.map +1 -1
  84. package/lib/typescript/commonjs/src/components/annotations/view-annotation/PointAnnotationNativeComponent.d.ts +2 -2
  85. package/lib/typescript/commonjs/src/components/annotations/view-annotation/PointAnnotationNativeComponent.d.ts.map +1 -1
  86. package/lib/typescript/commonjs/src/components/annotations/view-annotation/ViewAnnotation.d.ts +17 -6
  87. package/lib/typescript/commonjs/src/components/annotations/view-annotation/ViewAnnotation.d.ts.map +1 -1
  88. package/lib/typescript/commonjs/src/components/camera/Camera.d.ts.map +1 -1
  89. package/lib/typescript/commonjs/src/components/layer/Layer.d.ts +23 -59
  90. package/lib/typescript/commonjs/src/components/layer/Layer.d.ts.map +1 -1
  91. package/lib/typescript/commonjs/src/components/map/Map.d.ts +5 -8
  92. package/lib/typescript/commonjs/src/components/map/Map.d.ts.map +1 -1
  93. package/lib/typescript/commonjs/src/components/user-location/UserLocation.d.ts.map +1 -1
  94. package/lib/typescript/commonjs/src/components/user-location/UserLocationPuck.d.ts.map +1 -1
  95. package/lib/typescript/commonjs/src/components/user-location/UserLocationPuckHeading.d.ts.map +1 -1
  96. package/lib/typescript/commonjs/src/index.d.ts +2 -2
  97. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  98. package/lib/typescript/commonjs/src/types/MapLibreRNStyles.d.ts +10 -10
  99. package/lib/typescript/commonjs/src/types/MapLibreRNStyles.d.ts.map +1 -1
  100. package/lib/typescript/commonjs/src/utils/animated/AbstractAnimatedCoordinates.d.ts +13 -7
  101. package/lib/typescript/commonjs/src/utils/animated/AbstractAnimatedCoordinates.d.ts.map +1 -1
  102. package/lib/typescript/commonjs/src/utils/animated/Animated.d.ts +2 -0
  103. package/lib/typescript/commonjs/src/utils/animated/Animated.d.ts.map +1 -1
  104. package/lib/typescript/commonjs/src/utils/animated/AnimatedCoordinatesArray.d.ts +6 -6
  105. package/lib/typescript/commonjs/src/utils/animated/AnimatedCoordinatesArray.d.ts.map +1 -1
  106. package/lib/typescript/commonjs/src/utils/animated/AnimatedExtractCoordinateFromArray.d.ts +2 -2
  107. package/lib/typescript/commonjs/src/utils/animated/AnimatedExtractCoordinateFromArray.d.ts.map +1 -1
  108. package/lib/typescript/commonjs/src/utils/animated/AnimatedGeoJSON.d.ts +4 -5
  109. package/lib/typescript/commonjs/src/utils/animated/AnimatedGeoJSON.d.ts.map +1 -1
  110. package/lib/typescript/commonjs/src/utils/animated/AnimatedPoint.d.ts +20 -19
  111. package/lib/typescript/commonjs/src/utils/animated/AnimatedPoint.d.ts.map +1 -1
  112. package/lib/typescript/commonjs/src/utils/animated/AnimatedRouteCoordinatesArray.d.ts +4 -4
  113. package/lib/typescript/commonjs/src/utils/animated/AnimatedRouteCoordinatesArray.d.ts.map +1 -1
  114. package/lib/typescript/module/src/components/annotations/marker/Marker.d.ts +9 -4
  115. package/lib/typescript/module/src/components/annotations/marker/Marker.d.ts.map +1 -1
  116. package/lib/typescript/module/src/components/annotations/marker/MarkerViewNativeComponent.d.ts +2 -2
  117. package/lib/typescript/module/src/components/annotations/marker/MarkerViewNativeComponent.d.ts.map +1 -1
  118. package/lib/typescript/module/src/components/annotations/view-annotation/PointAnnotationNativeComponent.d.ts +2 -2
  119. package/lib/typescript/module/src/components/annotations/view-annotation/PointAnnotationNativeComponent.d.ts.map +1 -1
  120. package/lib/typescript/module/src/components/annotations/view-annotation/ViewAnnotation.d.ts +17 -6
  121. package/lib/typescript/module/src/components/annotations/view-annotation/ViewAnnotation.d.ts.map +1 -1
  122. package/lib/typescript/module/src/components/camera/Camera.d.ts.map +1 -1
  123. package/lib/typescript/module/src/components/layer/Layer.d.ts +23 -59
  124. package/lib/typescript/module/src/components/layer/Layer.d.ts.map +1 -1
  125. package/lib/typescript/module/src/components/map/Map.d.ts +5 -8
  126. package/lib/typescript/module/src/components/map/Map.d.ts.map +1 -1
  127. package/lib/typescript/module/src/components/user-location/UserLocation.d.ts.map +1 -1
  128. package/lib/typescript/module/src/components/user-location/UserLocationPuck.d.ts.map +1 -1
  129. package/lib/typescript/module/src/components/user-location/UserLocationPuckHeading.d.ts.map +1 -1
  130. package/lib/typescript/module/src/index.d.ts +2 -2
  131. package/lib/typescript/module/src/index.d.ts.map +1 -1
  132. package/lib/typescript/module/src/types/MapLibreRNStyles.d.ts +10 -10
  133. package/lib/typescript/module/src/types/MapLibreRNStyles.d.ts.map +1 -1
  134. package/lib/typescript/module/src/utils/animated/AbstractAnimatedCoordinates.d.ts +13 -7
  135. package/lib/typescript/module/src/utils/animated/AbstractAnimatedCoordinates.d.ts.map +1 -1
  136. package/lib/typescript/module/src/utils/animated/Animated.d.ts +2 -0
  137. package/lib/typescript/module/src/utils/animated/Animated.d.ts.map +1 -1
  138. package/lib/typescript/module/src/utils/animated/AnimatedCoordinatesArray.d.ts +6 -6
  139. package/lib/typescript/module/src/utils/animated/AnimatedCoordinatesArray.d.ts.map +1 -1
  140. package/lib/typescript/module/src/utils/animated/AnimatedExtractCoordinateFromArray.d.ts +2 -2
  141. package/lib/typescript/module/src/utils/animated/AnimatedExtractCoordinateFromArray.d.ts.map +1 -1
  142. package/lib/typescript/module/src/utils/animated/AnimatedGeoJSON.d.ts +4 -5
  143. package/lib/typescript/module/src/utils/animated/AnimatedGeoJSON.d.ts.map +1 -1
  144. package/lib/typescript/module/src/utils/animated/AnimatedPoint.d.ts +20 -19
  145. package/lib/typescript/module/src/utils/animated/AnimatedPoint.d.ts.map +1 -1
  146. package/lib/typescript/module/src/utils/animated/AnimatedRouteCoordinatesArray.d.ts +4 -4
  147. package/lib/typescript/module/src/utils/animated/AnimatedRouteCoordinatesArray.d.ts.map +1 -1
  148. package/package.json +11 -11
  149. package/src/components/annotations/LayerAnnotation.tsx +1 -1
  150. package/src/components/annotations/marker/Marker.tsx +13 -21
  151. package/src/components/annotations/marker/MarkerViewNativeComponent.ts +2 -2
  152. package/src/components/annotations/view-annotation/PointAnnotationNativeComponent.ts +2 -2
  153. package/src/components/annotations/view-annotation/ViewAnnotation.tsx +71 -75
  154. package/src/components/camera/Camera.tsx +2 -2
  155. package/src/components/layer/Layer.tsx +32 -78
  156. package/src/components/map/Map.tsx +7 -11
  157. package/src/components/sources/geojson-source/GeoJSONSource.tsx +2 -2
  158. package/src/components/sources/vector-source/VectorSource.tsx +2 -2
  159. package/src/components/user-location/UserLocation.tsx +30 -18
  160. package/src/components/user-location/UserLocationPuck.tsx +20 -20
  161. package/src/components/user-location/UserLocationPuckHeading.tsx +9 -10
  162. package/src/index.ts +5 -3
  163. package/src/types/MapLibreRNStyles.ts +10 -9
  164. package/src/utils/animated/AbstractAnimatedCoordinates.ts +16 -7
  165. package/src/utils/animated/{Animated.tsx → Animated.ts} +2 -4
  166. package/src/utils/animated/AnimatedCoordinatesArray.ts +8 -6
  167. package/src/utils/animated/AnimatedExtractCoordinateFromArray.ts +8 -9
  168. package/src/utils/animated/AnimatedGeoJSON.ts +21 -21
  169. package/src/utils/animated/AnimatedPoint.ts +74 -51
  170. package/src/utils/animated/AnimatedRouteCoordinatesArray.ts +9 -4
  171. package/android/src/main/res/layout/annotation.xml +0 -17
  172. /package/android/src/main/res/drawable-xxhdpi/{red_marker.png → default_marker.png} +0 -0
@@ -50,7 +50,8 @@ class MLRNMarkerView(
50
50
  override fun onChildViewRemoved(
51
51
  parent: View?,
52
52
  child: View?,
53
- ) {}
53
+ ) {
54
+ }
54
55
  },
55
56
  )
56
57
  for (i in 0 until view.childCount) {
@@ -1,16 +1,12 @@
1
1
  package org.maplibre.reactnative.components.annotations.markerview
2
2
 
3
3
  import android.content.Context
4
- import android.view.MotionEvent
5
4
  import android.view.ViewGroup
6
5
  import com.facebook.react.views.view.ReactViewGroup
7
6
 
8
7
  /**
9
- * Custom ReactViewGroup that allows content to render outside its bounds (#642).
10
- * This is used as a wrapper for Marker content to prevent clipping.
11
- *
12
8
  * Based on rnmapbox/maps implementation:
13
- * https://github.com/rnmapbox/maps/blob/main/android/src/main/java/com/rnmapbox/rnmbx/components/annotation/RNMBXMarkerViewContent.kt
9
+ * https://github.com/rnmapbox/maps/blob/512c50865f322fa89e0d20066b4a0fb10f080cb5/android/src/main/java/com/rnmapbox/rnmbx/components/annotation/RNMBXMarkerViewContent.kt
14
10
  */
15
11
  class MLRNMarkerViewContent(
16
12
  context: Context,
@@ -32,19 +28,18 @@ class MLRNMarkerViewContent(
32
28
  }
33
29
 
34
30
  /**
35
- * Request that the parent (MapView) not intercept touch events when touching marker content.
36
- * This allows TouchableOpacity, Pressable, etc. to receive touch events properly (#557, #1018).
31
+ * Returns the authoritative content size from the first child view.
32
+ * The child is laid out by React Native before this wrapper is added to the map,
33
+ * so its dimensions are reliable even before this view's own layout pass runs.
37
34
  */
38
- override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
39
- // Request that parent (MapView) doesn't intercept this touch sequence
40
- parent?.requestDisallowInterceptTouchEvent(true)
41
- return super.onInterceptTouchEvent(event)
35
+ fun getContentSize(): Pair<Float, Float> {
36
+ val child = getChildAt(0) ?: return Pair(width.toFloat(), height.toFloat())
37
+ val w = if (child.width > 0) child.width else width
38
+ val h = if (child.height > 0) child.height else height
39
+ return Pair(w.toFloat(), h.toFloat())
42
40
  }
43
41
  }
44
42
 
45
- /**
46
- * Extension function to disable all forms of clipping on a ViewGroup
47
- */
48
43
  private fun ViewGroup.allowRenderingOutside() {
49
44
  clipChildren = false
50
45
  clipToPadding = false
@@ -1,9 +1,8 @@
1
1
  package org.maplibre.reactnative.components.annotations.markerview
2
2
 
3
3
  import android.graphics.PointF
4
+ import android.graphics.RectF
4
5
  import android.view.View
5
- import android.view.ViewGroup
6
- import android.widget.FrameLayout
7
6
  import org.maplibre.android.geometry.LatLng
8
7
  import org.maplibre.android.maps.MapLibreMap
9
8
  import org.maplibre.android.maps.MapView
@@ -13,7 +12,7 @@ class MarkerViewManager(
13
12
  private val map: MapLibreMap,
14
13
  ) {
15
14
  data class MarkerInfo(
16
- val view: View,
15
+ val view: MLRNMarkerViewContent,
17
16
  var latLng: LatLng,
18
17
  var anchorX: Float = 0f,
19
18
  var anchorY: Float = 0f,
@@ -25,7 +24,7 @@ class MarkerViewManager(
25
24
  private var isDestroyed = false
26
25
 
27
26
  fun addMarker(
28
- view: View,
27
+ view: MLRNMarkerViewContent,
29
28
  latLng: LatLng,
30
29
  anchorX: Float = 0f,
31
30
  anchorY: Float = 0f,
@@ -35,12 +34,6 @@ class MarkerViewManager(
35
34
  val markerInfo = MarkerInfo(view, latLng, anchorX, anchorY, offsetX, offsetY)
36
35
  markers.add(markerInfo)
37
36
 
38
- if (view is ViewGroup) {
39
- view.clipChildren = false
40
- view.clipToPadding = false
41
- view.clipToOutline = false
42
- }
43
-
44
37
  if (view.parent == null) {
45
38
  mapView.clipChildren = false
46
39
  mapView.clipToPadding = false
@@ -73,8 +66,7 @@ class MarkerViewManager(
73
66
  private fun updateMarkerPosition(marker: MarkerInfo) {
74
67
  val view = marker.view
75
68
  val screenPos: PointF = map.projection.toScreenLocation(marker.latLng)
76
- val viewWidth = if (view.width > 0) view.width.toFloat() else view.measuredWidth.toFloat()
77
- val viewHeight = if (view.height > 0) view.height.toFloat() else view.measuredHeight.toFloat()
69
+ val (viewWidth, viewHeight) = view.getContentSize()
78
70
  val anchorOffsetX = viewWidth * marker.anchorX
79
71
  val anchorOffsetY = viewHeight * marker.anchorY
80
72
  view.x = screenPos.x - anchorOffsetX + marker.offsetX
@@ -83,6 +75,18 @@ class MarkerViewManager(
83
75
 
84
76
  fun findMarkerByView(view: View): MarkerInfo? = markers.find { it.view == view }
85
77
 
78
+ fun isPointInsideMarker(screenPoint: PointF): Boolean {
79
+ for (marker in markers) {
80
+ val v = marker.view
81
+ if (v.visibility != View.VISIBLE) continue
82
+ val (w, h) = v.getContentSize()
83
+ val rect = RectF(v.x, v.y, v.x + w, v.y + h)
84
+ if (rect.contains(screenPoint.x, screenPoint.y)) return true
85
+ }
86
+
87
+ return false
88
+ }
89
+
86
90
  fun updateMarkerCoordinate(
87
91
  markerInfo: MarkerInfo,
88
92
  latLng: LatLng,
@@ -4,6 +4,7 @@ import android.content.Context
4
4
  import android.graphics.Bitmap
5
5
  import android.graphics.PointF
6
6
  import android.view.View
7
+ import android.view.ViewGroup
7
8
  import com.facebook.react.bridge.ReactContext
8
9
  import com.facebook.react.uimanager.UIManagerHelper
9
10
  import org.maplibre.android.geometry.LatLng
@@ -26,18 +27,17 @@ class MLRNPointAnnotation(
26
27
  private var mMap: MapLibreMap? = null
27
28
  private var mMapView: MLRNMapView? = null
28
29
 
29
- private val mHasChildren = false
30
-
31
30
  private var mCoordinate: Point? = null
32
31
 
33
- public var mapLibreId: String? = null
34
- public var title: String? = null
32
+ var mapLibreId: String? = null
33
+ var title: String? = null
35
34
  private var mSnippet: String? = null
36
35
 
37
36
  private var mAnchor: FloatArray? = null
38
37
  private var mOffset: FloatArray? = null
39
- private val mIsSelected = false
40
38
  private var mDraggable = false
39
+ var selected = false
40
+ private set
41
41
 
42
42
  private var mChildView: View? = null
43
43
  private var mChildBitmap: Bitmap? = null
@@ -49,7 +49,7 @@ class MLRNPointAnnotation(
49
49
  private var mCalloutBitmapId: String? = null
50
50
 
51
51
  companion object {
52
- const val MARKER_IMAGE_ID: String = "MARKER_IMAGE_ID"
52
+ const val DEFAULT_MARKER: String = "DEFAULT_MARKER"
53
53
  }
54
54
 
55
55
  private val surfaceId: Int
@@ -115,7 +115,7 @@ class MLRNPointAnnotation(
115
115
  // Return children in consistent order: child view first, then callout
116
116
  return when {
117
117
  index == 0 && mChildView != null -> mChildView
118
- index == 0 && mChildView == null && mCalloutView != null -> mCalloutView
118
+ index == 0 && mCalloutView != null -> mCalloutView
119
119
  index == 1 && mChildView != null && mCalloutView != null -> mCalloutView
120
120
  else -> null
121
121
  }
@@ -139,6 +139,10 @@ class MLRNPointAnnotation(
139
139
  }
140
140
  addBitmapToStyle(mCalloutBitmap, mCalloutBitmapId)
141
141
  }
142
+
143
+ if (selected) {
144
+ mMapView?.selectAnnotation(this)
145
+ }
142
146
  }
143
147
 
144
148
  override fun removeFromMap(mapView: MLRNMapView) {
@@ -201,16 +205,12 @@ class MLRNPointAnnotation(
201
205
  refreshBitmap(v, v.left, v.top, v.right, v.bottom)
202
206
  }
203
207
 
204
- fun getLatLng(): LatLng? = GeoJSONUtils.toLatLng(mCoordinate)
205
-
206
208
  val annotationId: Long? get() = mAnnotation?.id
207
209
 
208
210
  fun setSnippet(snippet: String?) {
209
211
  mSnippet = snippet
210
212
  }
211
213
 
212
- fun getCalloutView(): View? = mCalloutView
213
-
214
214
  fun setLngLat(lngLat: DoubleArray?) {
215
215
  if (lngLat == null || lngLat.size < 2) {
216
216
  return
@@ -260,21 +260,37 @@ class MLRNPointAnnotation(
260
260
  }
261
261
  }
262
262
 
263
- fun getMarker(): Symbol? = mAnnotation
264
-
265
- fun onSelect(shouldSendEvent: Boolean) {
266
- if (mCalloutView != null) {
267
- makeCallout()
263
+ fun setSelectedAnnotation(selected: Boolean) {
264
+ if (mMapView != null && mAnnotation != null) {
265
+ if (selected) {
266
+ mMapView?.selectAnnotation(this)
267
+ } else {
268
+ mMapView?.deselectAnnotation(this)
269
+ }
270
+ } else {
271
+ this.selected = selected
268
272
  }
269
- if (shouldSendEvent) {
273
+ }
274
+
275
+ fun onSelect() {
276
+ if (!selected) {
277
+ selected = true
278
+ if (mCalloutView != null) {
279
+ makeCallout()
280
+ }
281
+
270
282
  emitEvent("onSelected")
271
283
  }
272
284
  }
273
285
 
274
286
  fun onDeselect() {
275
- emitEvent("onDeselected")
276
- if (mCalloutSymbol != null) {
277
- mMapView?.getSymbolManager()?.delete(mCalloutSymbol)
287
+ if (selected) {
288
+ selected = false
289
+ if (mCalloutSymbol != null) {
290
+ mMapView?.getSymbolManager()?.delete(mCalloutSymbol)
291
+ }
292
+
293
+ emitEvent("onDeselected")
278
294
  }
279
295
  }
280
296
 
@@ -325,12 +341,12 @@ class MLRNPointAnnotation(
325
341
  }
326
342
 
327
343
  private fun updateIconImage() {
328
- if (mChildView != null) {
344
+ if (mChildView != null && ((mChildView as? ViewGroup)?.childCount ?: 0) > 0) {
329
345
  if (mChildBitmapId != null) {
330
346
  mAnnotation?.iconImage = mChildBitmapId
331
347
  }
332
348
  } else {
333
- mAnnotation?.iconImage = MARKER_IMAGE_ID
349
+ mAnnotation?.iconImage = DEFAULT_MARKER
334
350
  mAnnotation?.iconAnchor = "bottom"
335
351
  }
336
352
  }
@@ -418,8 +434,8 @@ class MLRNPointAnnotation(
418
434
  private fun getScreenPosition(latLng: LatLng): PointF? {
419
435
  val screenPos = mMap?.projection?.toScreenLocation(latLng)
420
436
  val density = getDisplayDensity()
421
- screenPos?.x = screenPos?.x?.div(density) ?: 0f
422
- screenPos?.y = screenPos?.y?.div(density) ?: 0f
437
+ screenPos?.x = screenPos.x.div(density)
438
+ screenPos?.y = screenPos.y.div(density)
423
439
  return screenPos
424
440
  }
425
441
 
@@ -82,7 +82,8 @@ class MLRNPointAnnotationManager(
82
82
  annotation: MLRNPointAnnotation,
83
83
  selected: Boolean,
84
84
  ) {
85
- // Selection is handled by the map view
85
+ annotation
86
+ .setSelectedAnnotation(selected)
86
87
  }
87
88
 
88
89
  @ReactProp(name = "lngLat")
@@ -156,9 +156,6 @@ open class MLRNMapView(
156
156
 
157
157
  private var symbolManager: SymbolManager? = null
158
158
 
159
- private var activePointAnnotationAnnotationId: Long? = null
160
- private var pointAnnotationClicked = false
161
-
162
159
  private var markerViewManager: MarkerViewManager? = null
163
160
  private var offscreenAnnotationViewContainer: ViewGroup? = null
164
161
 
@@ -264,10 +261,6 @@ open class MLRNMapView(
264
261
  }
265
262
 
266
263
  is MLRNPointAnnotation -> {
267
- if (child.feature.annotationId == activePointAnnotationAnnotationId) {
268
- activePointAnnotationAnnotationId = null
269
- }
270
-
271
264
  child.feature.mapLibreId?.let { pointAnnotations.remove(it) }
272
265
  }
273
266
 
@@ -324,18 +317,11 @@ open class MLRNMapView(
324
317
  mapLibreMap!!.moveCamera(cameraUpdate, callback)
325
318
  }
326
319
 
327
- fun getPointAnnotationByMarkerID(markerID: Long): MLRNPointAnnotation? {
328
- for (key in pointAnnotations.keys) {
329
- val annotation = pointAnnotations[key]
330
-
331
- if (annotation != null && markerID == annotation.annotationId) {
332
- return annotation
333
- }
320
+ fun getPointAnnotationByAnnotationId(annotationId: Long): MLRNPointAnnotation? =
321
+ pointAnnotations.values.find {
322
+ it.annotationId == annotationId
334
323
  }
335
324
 
336
- return null
337
- }
338
-
339
325
  fun getSymbolManager(): SymbolManager = symbolManager!!
340
326
 
341
327
  interface FoundLayerCallback {
@@ -465,28 +451,24 @@ open class MLRNMapView(
465
451
  symbolManager = SymbolManager(this, this.mapLibreMap!!, style)
466
452
  symbolManager!!.setIconAllowOverlap(true)
467
453
  symbolManager!!.addClickListener { symbol ->
468
- onMarkerClick(symbol)
454
+ onPointAnnotationClick(symbol)
469
455
  true
470
456
  }
471
457
  symbolManager!!.addDragListener(
472
458
  object : OnSymbolDragListener {
473
459
  override fun onAnnotationDragStarted(symbol: Symbol) {
474
- pointAnnotationClicked = true
475
- val selectedMarkerID = symbol.id
476
- val annotation = getPointAnnotationByMarkerID(selectedMarkerID)
460
+ val selectedPointAnnotationID = symbol.id
461
+ val annotation = getPointAnnotationByAnnotationId(selectedPointAnnotationID)
477
462
  annotation?.onDragStart()
478
463
  }
479
464
 
480
465
  override fun onAnnotationDrag(symbol: Symbol) {
481
- val selectedMarkerID = symbol.id
482
- val annotation = getPointAnnotationByMarkerID(selectedMarkerID)
466
+ val annotation = getPointAnnotationByAnnotationId(symbol.id)
483
467
  annotation?.onDrag()
484
468
  }
485
469
 
486
470
  override fun onAnnotationDragFinished(symbol: Symbol) {
487
- pointAnnotationClicked = false
488
- val selectedMarkerID = symbol.id
489
- val annotation = getPointAnnotationByMarkerID(selectedMarkerID)
471
+ val annotation = getPointAnnotationByAnnotationId(symbol.id)
490
472
  annotation?.onDragEnd()
491
473
  }
492
474
  },
@@ -547,19 +529,14 @@ open class MLRNMapView(
547
529
  }
548
530
 
549
531
  override fun onMapClick(latLng: LatLng): Boolean {
550
- if (pointAnnotationClicked) {
551
- pointAnnotationClicked = false
552
- }
553
-
554
- if (activePointAnnotationAnnotationId != null) {
555
- val active = pointAnnotations.values.find { it.annotationId == activePointAnnotationAnnotationId }
556
- if (active != null) {
557
- deselectAnnotation(active)
558
- }
559
- }
532
+ pointAnnotations.values.find { it.selected }?.let { deselectAnnotation(it) }
560
533
 
561
534
  val screenPoint = mapLibreMap!!.projection.toScreenLocation(latLng)
562
535
 
536
+ if (markerViewManager?.isPointInsideMarker(screenPoint) == true) {
537
+ return true
538
+ }
539
+
563
540
  val hits: MutableMap<String, MutableList<Feature>?> = HashMap()
564
541
  val hitPressableSources: MutableList<MLRNPressableSource<*>> = ArrayList()
565
542
  for (pressableSource in this.pressableSources) {
@@ -567,10 +544,10 @@ open class MLRNMapView(
567
544
 
568
545
  val pointWithHitbox =
569
546
  RectF(
570
- screenPoint.x - hitbox.left,
571
- screenPoint.y - hitbox.top,
572
- screenPoint.x + hitbox.right,
573
- screenPoint.y + hitbox.bottom,
547
+ screenPoint.x - (hitbox.left * displayDensity),
548
+ screenPoint.y - (hitbox.top * displayDensity),
549
+ screenPoint.x + (hitbox.right * displayDensity),
550
+ screenPoint.y + (hitbox.bottom * displayDensity),
574
551
  )
575
552
 
576
553
  val features =
@@ -581,6 +558,9 @@ open class MLRNMapView(
581
558
  }
582
559
  }
583
560
 
561
+ screenPoint.x /= this.displayDensity
562
+ screenPoint.y /= this.displayDensity
563
+
584
564
  if (hits.isNotEmpty()) {
585
565
  val source = getPressableSourceWithHighestZIndex(hitPressableSources)
586
566
  if (source != null && source.hasOnPress) {
@@ -599,11 +579,14 @@ open class MLRNMapView(
599
579
  }
600
580
 
601
581
  override fun onMapLongClick(latLng: LatLng): Boolean {
602
- if (pointAnnotationClicked) {
603
- pointAnnotationClicked = false
582
+ val screenPoint = mapLibreMap!!.projection.toScreenLocation(latLng)
583
+
584
+ if (markerViewManager?.isPointInsideMarker(screenPoint) == true) {
585
+ return true
604
586
  }
605
587
 
606
- val screenPoint = mapLibreMap!!.projection.toScreenLocation(latLng)
588
+ screenPoint.x /= this.displayDensity
589
+ screenPoint.y /= this.displayDensity
607
590
 
608
591
  val event = MapPressEvent(surfaceId, id, "onLongPress", latLng, screenPoint)
609
592
  eventDispatcher?.dispatchEvent(event)
@@ -611,42 +594,24 @@ open class MLRNMapView(
611
594
  return false
612
595
  }
613
596
 
614
- fun onMarkerClick(symbol: Symbol) {
615
- pointAnnotationClicked = true
616
- val selectedMarkerID = symbol.id
617
-
618
- var activeAnnotation: MLRNPointAnnotation? = null
619
- var nextActiveAnnotation: MLRNPointAnnotation? = null
620
-
621
- for (key in pointAnnotations.keys) {
622
- val pointAnnotation = pointAnnotations[key]
623
- val currentAnnotationId = pointAnnotation!!.annotationId
624
-
625
- if (activePointAnnotationAnnotationId == currentAnnotationId) {
626
- activeAnnotation = pointAnnotation
627
- }
597
+ fun onPointAnnotationClick(nextSymbol: Symbol) {
598
+ val nextSelectedPointAnnotation =
599
+ getPointAnnotationByAnnotationId(nextSymbol.id) ?: return
628
600
 
629
- if (selectedMarkerID == currentAnnotationId && activePointAnnotationAnnotationId != currentAnnotationId) {
630
- nextActiveAnnotation = pointAnnotation
631
- }
632
- }
633
-
634
- if (activeAnnotation != null) {
635
- deselectAnnotation(activeAnnotation)
636
- }
637
-
638
- if (nextActiveAnnotation != null) {
639
- selectAnnotation(nextActiveAnnotation)
601
+ if (!nextSelectedPointAnnotation.selected) {
602
+ selectAnnotation(nextSelectedPointAnnotation)
640
603
  }
641
604
  }
642
605
 
643
- fun selectAnnotation(annotation: MLRNPointAnnotation) {
644
- activePointAnnotationAnnotationId = annotation.annotationId
645
- annotation.onSelect(true)
606
+ fun selectAnnotation(nextSelectedPointAnnotation: MLRNPointAnnotation) {
607
+ pointAnnotations.values
608
+ .filter { it.selected && it !== nextSelectedPointAnnotation }
609
+ .forEach { it.onDeselect() }
610
+
611
+ nextSelectedPointAnnotation.onSelect()
646
612
  }
647
613
 
648
614
  fun deselectAnnotation(annotation: MLRNPointAnnotation) {
649
- activePointAnnotationAnnotationId = null
650
615
  annotation.onDeselect()
651
616
  }
652
617
 
@@ -825,13 +790,12 @@ open class MLRNMapView(
825
790
  if (position.hasKey("right")) gravity = gravity or Gravity.END
826
791
  if (position.hasKey("top")) gravity = gravity or Gravity.TOP
827
792
  if (position.hasKey("bottom")) gravity = gravity or Gravity.BOTTOM
828
- val density = this.displayDensity
829
793
  val margins =
830
794
  intArrayOf(
831
- if (position.hasKey("left")) (density * position.getInt("left")).roundToInt() else 0,
832
- if (position.hasKey("top")) (density * position.getInt("top")).roundToInt() else 0,
833
- if (position.hasKey("right")) (density * position.getInt("right")).roundToInt() else 0,
834
- if (position.hasKey("bottom")) (density * position.getInt("bottom")).roundToInt() else 0,
795
+ if (position.hasKey("left")) (displayDensity * position.getInt("left")).roundToInt() else 0,
796
+ if (position.hasKey("top")) (displayDensity * position.getInt("top")).roundToInt() else 0,
797
+ if (position.hasKey("right")) (displayDensity * position.getInt("right")).roundToInt() else 0,
798
+ if (position.hasKey("bottom")) (displayDensity * position.getInt("bottom")).roundToInt() else 0,
835
799
  )
836
800
  setGravity(gravity)
837
801
  setMargins(margins)
@@ -937,8 +901,7 @@ open class MLRNMapView(
937
901
  layers: ReadableArray?,
938
902
  filter: Expression?,
939
903
  ): WritableArray {
940
- val density = this.displayDensity
941
- val screenPoint = PointF(point.x * density, point.y * density)
904
+ val screenPoint = PointF(point.x * displayDensity, point.y * displayDensity)
942
905
 
943
906
  val features =
944
907
  mapLibreMap!!.queryRenderedFeatures(
@@ -981,9 +944,8 @@ open class MLRNMapView(
981
944
 
982
945
  fun project(mapCoordinate: LatLng): WritableArray {
983
946
  val pointInView = mapLibreMap!!.projection.toScreenLocation(mapCoordinate)
984
- val density = this.displayDensity
985
- pointInView.x /= density
986
- pointInView.y /= density
947
+ pointInView.x /= displayDensity
948
+ pointInView.y /= displayDensity
987
949
  val payload: WritableArray = Arguments.createArray()
988
950
 
989
951
  payload.pushDouble(pointInView.x.toDouble())
@@ -993,9 +955,8 @@ open class MLRNMapView(
993
955
  }
994
956
 
995
957
  fun unproject(pointInView: PointF): WritableArray {
996
- val density = this.displayDensity
997
- pointInView.x *= density
998
- pointInView.y *= density
958
+ pointInView.x *= displayDensity
959
+ pointInView.y *= displayDensity
999
960
 
1000
961
  val latLng = mapLibreMap!!.projection.fromScreenLocation(pointInView)
1001
962
 
@@ -1348,7 +1309,7 @@ open class MLRNMapView(
1348
1309
  }
1349
1310
 
1350
1311
  private fun getPressableSourceWithHighestZIndex(sources: MutableList<MLRNPressableSource<*>>?): MLRNPressableSource<*>? {
1351
- if (sources == null || sources.isEmpty()) {
1312
+ if (sources.isNullOrEmpty()) {
1352
1313
  return null
1353
1314
  }
1354
1315
 
@@ -1401,10 +1362,10 @@ open class MLRNMapView(
1401
1362
  */
1402
1363
  private fun setUpImage(loadedStyle: Style) {
1403
1364
  loadedStyle.addImage(
1404
- "MARKER_IMAGE_ID",
1365
+ MLRNPointAnnotation.DEFAULT_MARKER,
1405
1366
  BitmapFactory.decodeResource(
1406
1367
  this.resources,
1407
- R.drawable.red_marker,
1368
+ R.drawable.default_marker,
1408
1369
  ),
1409
1370
  )
1410
1371
  }
@@ -1,6 +1,7 @@
1
1
  #import "MLRNPointAnnotation.h"
2
2
  #import <React/UIView+React.h>
3
3
  #import "MLRNMapTouchEvent.h"
4
+ #import "MLRNMapView.h"
4
5
  #import "MLRNUtils.h"
5
6
 
6
7
  const float CENTER_X_OFFSET_BASE = -0.5f;
@@ -75,6 +76,9 @@ const float CENTER_Y_OFFSET_BASE = -0.5f;
75
76
  _reactSelected = reactSelected;
76
77
 
77
78
  if (_map != nil) {
79
+ if ([_map isKindOfClass:[MLRNMapView class]]) {
80
+ ((MLRNMapView *)_map).annotationSelected = YES;
81
+ }
78
82
  if (_reactSelected) {
79
83
  [_map selectAnnotation:self animated:NO completionHandler:nil];
80
84
  } else {
@@ -120,8 +124,22 @@ const float CENTER_Y_OFFSET_BASE = -0.5f;
120
124
  BOOL hasCustomChildren = (self.reactSubviews.count > 0) || (self.customChildCount > 0);
121
125
 
122
126
  if (!hasCustomChildren) {
123
- // default pin view
124
- return nil;
127
+ // Replicate MLNMapView's to allow unified tap/selection behavior.
128
+ NSBundle *mapLibreBundle = [NSBundle bundleForClass:[MLNMapView class]];
129
+ UIImage *pinImage = [UIImage imageNamed:@"default_marker"
130
+ inBundle:mapLibreBundle
131
+ compatibleWithTraitCollection:nil];
132
+
133
+ UIImageView *pinImageView = [[UIImageView alloc] initWithImage:pinImage];
134
+ [pinImageView sizeToFit];
135
+
136
+ MLNAnnotationView *defaultView = [[MLNAnnotationView alloc] initWithReuseIdentifier:nil];
137
+ defaultView.bounds = pinImageView.bounds;
138
+ [defaultView addSubview:pinImageView];
139
+ defaultView.centerOffset = CGVectorMake(0, 0);
140
+ defaultView.enabled = YES;
141
+ [defaultView addGestureRecognizer:customViewTap];
142
+ return defaultView;
125
143
  } else {
126
144
  // custom view
127
145
  self.enabled = YES;
@@ -143,6 +161,9 @@ const float CENTER_Y_OFFSET_BASE = -0.5f;
143
161
  }
144
162
 
145
163
  - (void)_handleTap:(UITapGestureRecognizer *)recognizer {
164
+ if ([_map isKindOfClass:[MLRNMapView class]]) {
165
+ ((MLRNMapView *)_map).annotationSelected = YES;
166
+ }
146
167
  [_map selectAnnotation:self animated:NO completionHandler:nil];
147
168
  }
148
169
 
@@ -238,25 +238,15 @@ using namespace facebook::react;
238
238
  const auto &newViewProps = *std::static_pointer_cast<MLRNPointAnnotationProps const>(props);
239
239
 
240
240
  if (oldViewProps.id != newViewProps.id) {
241
- NSString *idValue = [NSString stringWithCString:newViewProps.id.c_str()
242
- encoding:NSUTF8StringEncoding];
243
- [_view setId:idValue];
241
+ [_view setId:RCTNSStringFromString(newViewProps.id)];
244
242
  }
245
243
 
246
244
  if (oldViewProps.title != newViewProps.title) {
247
- NSString *titleValue = newViewProps.title.empty()
248
- ? nil
249
- : [NSString stringWithCString:newViewProps.title.c_str()
250
- encoding:NSUTF8StringEncoding];
251
- [_view setReactTitle:titleValue];
245
+ [_view setReactTitle:RCTNSStringFromStringNilIfEmpty(newViewProps.title)];
252
246
  }
253
247
 
254
248
  if (oldViewProps.snippet != newViewProps.snippet) {
255
- NSString *snippetValue = newViewProps.snippet.empty()
256
- ? nil
257
- : [NSString stringWithCString:newViewProps.snippet.c_str()
258
- encoding:NSUTF8StringEncoding];
259
- [_view setReactSnippet:snippetValue];
249
+ [_view setReactSnippet:RCTNSStringFromStringNilIfEmpty(newViewProps.snippet)];
260
250
  }
261
251
 
262
252
  if (oldViewProps.selected != newViewProps.selected) {
@@ -24,8 +24,6 @@ using namespace facebook::react;
24
24
 
25
25
  - (instancetype)initWithFrame:(CGRect)frame {
26
26
  if (self = [super initWithFrame:frame]) {
27
- static const auto defaultProps = std::make_shared<const MLRNCameraProps>();
28
- _props = defaultProps;
29
27
  [self prepareView];
30
28
  }
31
29
 
@@ -34,11 +32,14 @@ using namespace facebook::react;
34
32
 
35
33
  - (void)prepareForRecycle {
36
34
  [super prepareForRecycle];
37
- [_view setInitialViewState:nil];
38
- [_view setStop:nil];
35
+ [self prepareView];
39
36
  }
40
37
 
41
38
  - (void)prepareView {
39
+ static const auto defaultProps = std::make_shared<const MLRNCameraProps>();
40
+
41
+ _props = defaultProps;
42
+
42
43
  _view = [[MLRNCamera alloc] init];
43
44
 
44
45
  // Capture weak self reference to prevent retain cycle