@lugg/maps 0.2.0-alpha.9 → 1.0.0-beta.1
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.
- package/README.md +21 -20
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/luggmaps/LuggCalloutView.kt +74 -0
- package/android/src/main/java/com/luggmaps/LuggCalloutViewManager.kt +38 -0
- package/android/src/main/java/com/luggmaps/LuggMapView.kt +290 -0
- package/android/src/main/java/com/luggmaps/{LuggGoogleMapViewManager.kt → LuggMapViewManager.kt} +99 -36
- package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +11 -14
- package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +187 -21
- package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +28 -0
- package/android/src/main/java/com/luggmaps/LuggPackage.kt +8 -4
- package/android/src/main/java/com/luggmaps/LuggPolygonView.kt +85 -0
- package/android/src/main/java/com/luggmaps/LuggPolygonViewManager.kt +100 -0
- package/android/src/main/java/com/luggmaps/LuggPolylineView.kt +16 -0
- package/android/src/main/java/com/luggmaps/LuggPolylineViewManager.kt +22 -0
- package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +874 -0
- package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +60 -0
- package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +89 -24
- package/android/src/main/java/com/luggmaps/events/LongPressEvent.kt +29 -0
- package/android/src/main/java/com/luggmaps/events/MarkerDragEvent.kt +41 -0
- package/android/src/main/java/com/luggmaps/events/MarkerPressEvent.kt +34 -0
- package/android/src/main/java/com/luggmaps/events/PolygonPressEvent.kt +12 -0
- package/android/src/main/java/com/luggmaps/events/PressEvent.kt +29 -0
- package/ios/LuggCalloutView.h +23 -0
- package/ios/LuggCalloutView.mm +145 -0
- package/ios/LuggMapView.h +9 -0
- package/ios/LuggMapView.mm +343 -0
- package/ios/LuggMarkerView.h +15 -0
- package/ios/LuggMarkerView.mm +136 -2
- package/ios/LuggPolygonView.h +31 -0
- package/ios/LuggPolygonView.mm +151 -0
- package/ios/LuggPolylineView.h +4 -0
- package/ios/LuggPolylineView.mm +23 -0
- package/ios/core/AppleMapProvider.h +15 -0
- package/ios/core/AppleMapProvider.mm +1173 -0
- package/ios/core/GMSPolylineAnimator.h +3 -0
- package/ios/core/GMSPolylineAnimator.m +101 -15
- package/ios/core/GoogleMapProvider.h +13 -0
- package/ios/core/GoogleMapProvider.mm +798 -0
- package/ios/core/LuggAnnotationView.h +12 -0
- package/ios/core/LuggAnnotationView.mm +55 -0
- package/ios/core/MKPolylineAnimator.h +4 -0
- package/ios/core/MKPolylineAnimator.m +167 -42
- package/ios/core/MapProviderDelegate.h +84 -0
- package/ios/core/PolylineAnimatorBase.h +24 -1
- package/ios/core/PolylineAnimatorBase.m +82 -19
- package/ios/events/LongPressEvent.h +29 -0
- package/ios/events/MarkerDragEvent.h +69 -0
- package/ios/events/MarkerPressEvent.h +29 -0
- package/ios/events/PolygonPressEvent.h +20 -0
- package/ios/events/PressEvent.h +29 -0
- package/ios/extensions/MKMapView+Zoom.h +2 -0
- package/ios/extensions/MKMapView+Zoom.m +14 -4
- package/lib/module/MapProvider.js +2 -4
- package/lib/module/MapProvider.js.map +1 -1
- package/lib/module/MapProvider.web.js +14 -7
- package/lib/module/MapProvider.web.js.map +1 -1
- package/lib/module/MapView.js +33 -16
- package/lib/module/MapView.js.map +1 -1
- package/lib/module/MapView.web.js +296 -181
- package/lib/module/MapView.web.js.map +1 -1
- package/lib/module/components/GeoJson.js +159 -0
- package/lib/module/components/GeoJson.js.map +1 -0
- package/lib/module/components/GeoJson.types.js +4 -0
- package/lib/module/components/GeoJson.types.js.map +1 -0
- package/lib/module/components/Marker.js +49 -8
- package/lib/module/components/Marker.js.map +1 -1
- package/lib/module/components/Marker.types.js +4 -0
- package/lib/module/components/Marker.types.js.map +1 -0
- package/lib/module/components/Marker.web.js +159 -24
- package/lib/module/components/Marker.web.js.map +1 -1
- package/lib/module/components/Polygon.js +46 -0
- package/lib/module/components/Polygon.js.map +1 -0
- package/lib/module/components/Polygon.types.js +4 -0
- package/lib/module/components/Polygon.types.js.map +1 -0
- package/lib/module/components/Polygon.web.js +87 -0
- package/lib/module/components/Polygon.web.js.map +1 -0
- package/lib/module/components/Polyline.js +17 -4
- package/lib/module/components/Polyline.js.map +1 -1
- package/lib/module/components/Polyline.types.js +4 -0
- package/lib/module/components/Polyline.types.js.map +1 -0
- package/lib/module/components/Polyline.web.js +108 -31
- package/lib/module/components/Polyline.web.js.map +1 -1
- package/lib/module/components/index.js +4 -2
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/components/index.web.js +2 -0
- package/lib/module/components/index.web.js.map +1 -1
- package/lib/module/fabric/LuggCalloutViewNativeComponent.ts +20 -0
- package/lib/module/fabric/{LuggGoogleMapViewNativeComponent.ts → LuggMapViewNativeComponent.ts} +43 -7
- package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +49 -1
- package/lib/module/fabric/LuggPolygonViewNativeComponent.ts +25 -0
- package/lib/module/fabric/LuggPolylineViewNativeComponent.ts +8 -0
- package/lib/module/index.js +4 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +4 -1
- package/lib/module/index.web.js.map +1 -1
- package/lib/typescript/src/MapProvider.d.ts +1 -1
- package/lib/typescript/src/MapProvider.d.ts.map +1 -1
- package/lib/typescript/src/MapProvider.web.d.ts +23 -1
- package/lib/typescript/src/MapProvider.web.d.ts.map +1 -1
- package/lib/typescript/src/MapView.d.ts +4 -4
- package/lib/typescript/src/MapView.d.ts.map +1 -1
- package/lib/typescript/src/MapView.types.d.ts +35 -9
- package/lib/typescript/src/MapView.types.d.ts.map +1 -1
- package/lib/typescript/src/MapView.web.d.ts +2 -11
- package/lib/typescript/src/MapView.web.d.ts.map +1 -1
- package/lib/typescript/src/components/GeoJson.d.ts +4 -0
- package/lib/typescript/src/components/GeoJson.d.ts.map +1 -0
- package/lib/typescript/src/components/GeoJson.types.d.ts +89 -0
- package/lib/typescript/src/components/GeoJson.types.d.ts.map +1 -0
- package/lib/typescript/src/components/Marker.d.ts +6 -33
- package/lib/typescript/src/components/Marker.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.types.d.ts +100 -0
- package/lib/typescript/src/components/Marker.types.d.ts.map +1 -0
- package/lib/typescript/src/components/Marker.web.d.ts +2 -5
- package/lib/typescript/src/components/Marker.web.d.ts.map +1 -1
- package/lib/typescript/src/components/Polygon.d.ts +10 -0
- package/lib/typescript/src/components/Polygon.d.ts.map +1 -0
- package/lib/typescript/src/components/Polygon.types.d.ts +33 -0
- package/lib/typescript/src/components/Polygon.types.d.ts.map +1 -0
- package/lib/typescript/src/components/Polygon.web.d.ts +3 -0
- package/lib/typescript/src/components/Polygon.web.d.ts.map +1 -0
- package/lib/typescript/src/components/Polyline.d.ts +6 -21
- package/lib/typescript/src/components/Polyline.d.ts.map +1 -1
- package/lib/typescript/src/components/Polyline.types.d.ts +53 -0
- package/lib/typescript/src/components/Polyline.types.d.ts.map +1 -0
- package/lib/typescript/src/components/Polyline.web.d.ts +2 -5
- package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -1
- package/lib/typescript/src/components/index.d.ts +8 -2
- package/lib/typescript/src/components/index.d.ts.map +1 -1
- package/lib/typescript/src/components/index.web.d.ts +6 -2
- package/lib/typescript/src/components/index.web.d.ts.map +1 -1
- package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts +13 -0
- package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/{LuggGoogleMapViewNativeComponent.d.ts → LuggMapViewNativeComponent.d.ts} +30 -4
- package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +45 -1
- package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/fabric/LuggPolygonViewNativeComponent.d.ts +18 -0
- package/lib/typescript/src/fabric/LuggPolygonViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts +7 -0
- package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +11 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +9 -1
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +11 -0
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +11 -9
- package/src/MapProvider.tsx +1 -3
- package/src/MapProvider.web.tsx +22 -3
- package/src/MapView.tsx +32 -26
- package/src/MapView.types.ts +43 -9
- package/src/MapView.web.tsx +368 -210
- package/src/components/GeoJson.tsx +221 -0
- package/src/components/GeoJson.types.ts +118 -0
- package/src/components/Marker.tsx +75 -38
- package/src/components/Marker.types.ts +102 -0
- package/src/components/Marker.web.tsx +197 -19
- package/src/components/Polygon.tsx +52 -0
- package/src/components/Polygon.types.ts +33 -0
- package/src/components/Polygon.web.tsx +104 -0
- package/src/components/Polyline.tsx +23 -22
- package/src/components/Polyline.types.ts +55 -0
- package/src/components/Polyline.web.tsx +151 -37
- package/src/components/index.ts +17 -2
- package/src/components/index.web.ts +6 -2
- package/src/fabric/LuggCalloutViewNativeComponent.ts +20 -0
- package/src/fabric/{LuggGoogleMapViewNativeComponent.ts → LuggMapViewNativeComponent.ts} +43 -7
- package/src/fabric/LuggMarkerViewNativeComponent.ts +49 -1
- package/src/fabric/LuggPolygonViewNativeComponent.ts +25 -0
- package/src/fabric/LuggPolylineViewNativeComponent.ts +8 -0
- package/src/index.ts +30 -1
- package/src/index.web.ts +16 -1
- package/src/types.ts +13 -0
- package/android/src/main/java/com/luggmaps/LuggGoogleMapView.kt +0 -511
- package/ios/LuggAppleMapView.h +0 -16
- package/ios/LuggAppleMapView.mm +0 -592
- package/ios/LuggGoogleMapView.h +0 -13
- package/ios/LuggGoogleMapView.mm +0 -455
- package/lib/module/fabric/LuggAppleMapViewNativeComponent.ts +0 -83
- package/lib/typescript/src/fabric/LuggAppleMapViewNativeComponent.d.ts +0 -54
- package/lib/typescript/src/fabric/LuggAppleMapViewNativeComponent.d.ts.map +0 -1
- package/lib/typescript/src/fabric/LuggGoogleMapViewNativeComponent.d.ts.map +0 -1
- package/src/fabric/LuggAppleMapViewNativeComponent.ts +0 -83
|
@@ -0,0 +1,874 @@
|
|
|
1
|
+
package com.luggmaps.core
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.view.View
|
|
6
|
+
import android.widget.ImageView
|
|
7
|
+
import androidx.core.graphics.createBitmap
|
|
8
|
+
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
9
|
+
import com.google.android.gms.maps.CameraUpdateFactory
|
|
10
|
+
import com.google.android.gms.maps.GoogleMap
|
|
11
|
+
import com.google.android.gms.maps.GoogleMapOptions
|
|
12
|
+
import com.google.android.gms.maps.MapView
|
|
13
|
+
import com.google.android.gms.maps.OnMapReadyCallback
|
|
14
|
+
import com.google.android.gms.maps.model.AdvancedMarker
|
|
15
|
+
import com.google.android.gms.maps.model.AdvancedMarkerOptions
|
|
16
|
+
import com.google.android.gms.maps.model.BitmapDescriptorFactory
|
|
17
|
+
import com.google.android.gms.maps.model.LatLng
|
|
18
|
+
import com.google.android.gms.maps.model.MapColorScheme
|
|
19
|
+
import com.google.android.gms.maps.model.Marker
|
|
20
|
+
import com.google.android.gms.maps.model.Polygon
|
|
21
|
+
import com.google.android.gms.maps.model.PolygonOptions
|
|
22
|
+
import com.google.android.gms.maps.model.PolylineOptions
|
|
23
|
+
import com.luggmaps.LuggCalloutView
|
|
24
|
+
import com.luggmaps.LuggMapWrapperView
|
|
25
|
+
import com.luggmaps.LuggMarkerView
|
|
26
|
+
import com.luggmaps.LuggMarkerViewDelegate
|
|
27
|
+
import com.luggmaps.LuggPolygonView
|
|
28
|
+
import com.luggmaps.LuggPolygonViewDelegate
|
|
29
|
+
import com.luggmaps.LuggPolylineView
|
|
30
|
+
import com.luggmaps.LuggPolylineViewDelegate
|
|
31
|
+
|
|
32
|
+
class GoogleMapProvider(private val context: Context) :
|
|
33
|
+
MapProvider,
|
|
34
|
+
OnMapReadyCallback,
|
|
35
|
+
LuggMarkerViewDelegate,
|
|
36
|
+
LuggPolylineViewDelegate,
|
|
37
|
+
LuggPolygonViewDelegate,
|
|
38
|
+
GoogleMap.OnCameraMoveStartedListener,
|
|
39
|
+
GoogleMap.OnCameraMoveListener,
|
|
40
|
+
GoogleMap.OnCameraIdleListener,
|
|
41
|
+
GoogleMap.OnMapClickListener,
|
|
42
|
+
GoogleMap.OnMapLongClickListener,
|
|
43
|
+
GoogleMap.OnPolygonClickListener,
|
|
44
|
+
GoogleMap.OnMarkerClickListener,
|
|
45
|
+
GoogleMap.OnMarkerDragListener,
|
|
46
|
+
GoogleMap.InfoWindowAdapter {
|
|
47
|
+
|
|
48
|
+
override var delegate: MapProviderDelegate? = null
|
|
49
|
+
override val isMapReady: Boolean get() = _isMapReady
|
|
50
|
+
|
|
51
|
+
var mapId: String = DEMO_MAP_ID
|
|
52
|
+
|
|
53
|
+
private var wrapperView: LuggMapWrapperView? = null
|
|
54
|
+
private var mapView: MapView? = null
|
|
55
|
+
private var googleMap: GoogleMap? = null
|
|
56
|
+
private var _isMapReady = false
|
|
57
|
+
private var isDragging = false
|
|
58
|
+
private val pendingMarkerViews = mutableSetOf<LuggMarkerView>()
|
|
59
|
+
private val pendingPolylineViews = mutableSetOf<LuggPolylineView>()
|
|
60
|
+
private val pendingPolygonViews = mutableSetOf<LuggPolygonView>()
|
|
61
|
+
private val polylineAnimators = mutableMapOf<LuggPolylineView, PolylineAnimator>()
|
|
62
|
+
private val polygonToViewMap = mutableMapOf<Polygon, LuggPolygonView>()
|
|
63
|
+
private val markerToViewMap = mutableMapOf<Marker, LuggMarkerView>()
|
|
64
|
+
private val liveMarkerViews = mutableSetOf<LuggMarkerView>()
|
|
65
|
+
private var activeNonBubbledMarker: Marker? = null
|
|
66
|
+
private var tapLocation: LatLng? = null
|
|
67
|
+
|
|
68
|
+
// Initial camera settings
|
|
69
|
+
private var initialLatitude: Double = 0.0
|
|
70
|
+
private var initialLongitude: Double = 0.0
|
|
71
|
+
private var initialZoom: Float = 10f
|
|
72
|
+
|
|
73
|
+
// UI settings
|
|
74
|
+
private var zoomEnabled: Boolean = true
|
|
75
|
+
private var scrollEnabled: Boolean = true
|
|
76
|
+
private var rotateEnabled: Boolean = true
|
|
77
|
+
private var pitchEnabled: Boolean = true
|
|
78
|
+
private var userLocationEnabled: Boolean = false
|
|
79
|
+
private var userLocationButtonEnabled: Boolean = false
|
|
80
|
+
|
|
81
|
+
// Zoom limits
|
|
82
|
+
private var minZoom: Float? = null
|
|
83
|
+
private var maxZoom: Float? = null
|
|
84
|
+
|
|
85
|
+
// Theme
|
|
86
|
+
private var theme: String = "system"
|
|
87
|
+
|
|
88
|
+
// Edge Insets
|
|
89
|
+
private var edgeInsets: EdgeInsets = EdgeInsets()
|
|
90
|
+
|
|
91
|
+
// region MapProvider
|
|
92
|
+
|
|
93
|
+
override fun initializeMap(wrapperView: View, latitude: Double, longitude: Double, zoom: Float) {
|
|
94
|
+
if (mapView != null) return
|
|
95
|
+
|
|
96
|
+
initialLatitude = latitude
|
|
97
|
+
initialLongitude = longitude
|
|
98
|
+
initialZoom = zoom
|
|
99
|
+
|
|
100
|
+
val wrapper = wrapperView as LuggMapWrapperView
|
|
101
|
+
this.wrapperView = wrapper
|
|
102
|
+
|
|
103
|
+
val options = GoogleMapOptions().mapId(mapId)
|
|
104
|
+
mapView = MapView(context, options).also { view ->
|
|
105
|
+
view.onCreate(null)
|
|
106
|
+
view.onResume()
|
|
107
|
+
view.getMapAsync(this)
|
|
108
|
+
wrapper.addView(view)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
override fun destroy() {
|
|
113
|
+
dismissNonBubbledCallout()
|
|
114
|
+
for (markerView in liveMarkerViews) {
|
|
115
|
+
markerView.onUpdate = null
|
|
116
|
+
}
|
|
117
|
+
liveMarkerViews.clear()
|
|
118
|
+
pendingMarkerViews.clear()
|
|
119
|
+
pendingPolylineViews.clear()
|
|
120
|
+
pendingPolygonViews.clear()
|
|
121
|
+
polylineAnimators.values.forEach { it.destroy() }
|
|
122
|
+
polylineAnimators.clear()
|
|
123
|
+
polygonToViewMap.clear()
|
|
124
|
+
markerToViewMap.clear()
|
|
125
|
+
wrapperView?.touchEventHandler = null
|
|
126
|
+
wrapperView = null
|
|
127
|
+
googleMap?.setOnCameraMoveStartedListener(null)
|
|
128
|
+
googleMap?.setOnCameraMoveListener(null)
|
|
129
|
+
googleMap?.setOnCameraIdleListener(null)
|
|
130
|
+
googleMap?.setOnMapClickListener(null)
|
|
131
|
+
googleMap?.setOnMapLongClickListener(null)
|
|
132
|
+
googleMap?.setOnPolygonClickListener(null)
|
|
133
|
+
googleMap?.setOnMarkerClickListener(null)
|
|
134
|
+
googleMap?.setOnMarkerDragListener(null)
|
|
135
|
+
googleMap?.setInfoWindowAdapter(null)
|
|
136
|
+
googleMap?.clear()
|
|
137
|
+
googleMap = null
|
|
138
|
+
_isMapReady = false
|
|
139
|
+
mapView?.onPause()
|
|
140
|
+
mapView?.onDestroy()
|
|
141
|
+
mapView = null
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
override fun onMapReady(map: GoogleMap) {
|
|
145
|
+
googleMap = map
|
|
146
|
+
_isMapReady = true
|
|
147
|
+
|
|
148
|
+
val position = LatLng(initialLatitude, initialLongitude)
|
|
149
|
+
map.moveCamera(CameraUpdateFactory.newLatLngZoom(position, initialZoom))
|
|
150
|
+
|
|
151
|
+
map.setOnCameraMoveStartedListener(this)
|
|
152
|
+
map.setOnCameraMoveListener(this)
|
|
153
|
+
map.setOnCameraIdleListener(this)
|
|
154
|
+
map.setOnMapClickListener(this)
|
|
155
|
+
map.setOnMapLongClickListener(this)
|
|
156
|
+
map.setOnPolygonClickListener(this)
|
|
157
|
+
map.setOnMarkerClickListener(this)
|
|
158
|
+
map.setOnMarkerDragListener(this)
|
|
159
|
+
map.setInfoWindowAdapter(this)
|
|
160
|
+
|
|
161
|
+
wrapperView?.touchEventHandler = { event ->
|
|
162
|
+
if (event.action == android.view.MotionEvent.ACTION_DOWN) {
|
|
163
|
+
tapLocation = map.projection.fromScreenLocation(android.graphics.Point(event.x.toInt(), event.y.toInt()))
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
applyUiSettings()
|
|
168
|
+
applyZoomLimits()
|
|
169
|
+
applyEdgeInsets()
|
|
170
|
+
applyTheme()
|
|
171
|
+
applyUserLocation()
|
|
172
|
+
processPendingMarkers()
|
|
173
|
+
processPendingPolylines()
|
|
174
|
+
processPendingPolygons()
|
|
175
|
+
|
|
176
|
+
delegate?.mapProviderDidReady()
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// endregion
|
|
180
|
+
|
|
181
|
+
// region Camera Listeners
|
|
182
|
+
|
|
183
|
+
override fun onCameraMoveStarted(reason: Int) {
|
|
184
|
+
isDragging = reason == GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE
|
|
185
|
+
if (isDragging) {
|
|
186
|
+
polylineAnimators.values.forEach { it.pause() }
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
override fun onCameraMove() {
|
|
191
|
+
val map = googleMap ?: return
|
|
192
|
+
val position = map.cameraPosition
|
|
193
|
+
delegate?.mapProviderDidMoveCamera(position.target.latitude, position.target.longitude, position.zoom, isDragging)
|
|
194
|
+
positionLiveMarkers()
|
|
195
|
+
positionNonBubbledCallout()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
override fun onCameraIdle() {
|
|
199
|
+
val map = googleMap ?: return
|
|
200
|
+
val position = map.cameraPosition
|
|
201
|
+
delegate?.mapProviderDidIdleCamera(position.target.latitude, position.target.longitude, position.zoom, isDragging)
|
|
202
|
+
if (isDragging) {
|
|
203
|
+
polylineAnimators.values.forEach { it.resume() }
|
|
204
|
+
}
|
|
205
|
+
isDragging = false
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
override fun onMapClick(latLng: LatLng) {
|
|
209
|
+
dismissNonBubbledCallout()
|
|
210
|
+
val map = googleMap ?: return
|
|
211
|
+
val point = map.projection.toScreenLocation(latLng)
|
|
212
|
+
delegate?.mapProviderDidPress(latLng.latitude, latLng.longitude, point.x.toFloat(), point.y.toFloat())
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
override fun onMapLongClick(latLng: LatLng) {
|
|
216
|
+
val map = googleMap ?: return
|
|
217
|
+
val point = map.projection.toScreenLocation(latLng)
|
|
218
|
+
delegate?.mapProviderDidLongPress(latLng.latitude, latLng.longitude, point.x.toFloat(), point.y.toFloat())
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
override fun onPolygonClick(polygon: Polygon) {
|
|
222
|
+
val polygonView = polygonToViewMap[polygon]
|
|
223
|
+
if (polygonView?.tappable == true) {
|
|
224
|
+
polygonView.emitPressEvent()
|
|
225
|
+
} else {
|
|
226
|
+
onMapClick(tapLocation ?: return)
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
override fun onMarkerClick(marker: Marker): Boolean {
|
|
231
|
+
dismissNonBubbledCallout()
|
|
232
|
+
|
|
233
|
+
markerToViewMap[marker]?.let { view ->
|
|
234
|
+
val point = googleMap?.projection?.toScreenLocation(marker.position)
|
|
235
|
+
view.emitPressEvent(point?.x?.toFloat() ?: 0f, point?.y?.toFloat() ?: 0f)
|
|
236
|
+
|
|
237
|
+
val calloutView = view.calloutView
|
|
238
|
+
if (calloutView != null && !calloutView.bubbled && calloutView.hasCustomContent) {
|
|
239
|
+
googleMap?.animateCamera(CameraUpdateFactory.newLatLng(marker.position))
|
|
240
|
+
showNonBubbledCallout(marker, calloutView)
|
|
241
|
+
return true
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return false
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
override fun onMarkerDragStart(marker: Marker) {
|
|
248
|
+
markerToViewMap[marker]?.let { view ->
|
|
249
|
+
view.isDragging = true
|
|
250
|
+
view.setCoordinate(marker.position.latitude, marker.position.longitude)
|
|
251
|
+
val point = googleMap?.projection?.toScreenLocation(marker.position)
|
|
252
|
+
view.emitDragStartEvent(point?.x?.toFloat() ?: 0f, point?.y?.toFloat() ?: 0f)
|
|
253
|
+
if (!view.rasterize) positionLiveMarker(view)
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
override fun onMarkerDrag(marker: Marker) {
|
|
258
|
+
markerToViewMap[marker]?.let { view ->
|
|
259
|
+
view.setCoordinate(marker.position.latitude, marker.position.longitude)
|
|
260
|
+
val point = googleMap?.projection?.toScreenLocation(marker.position)
|
|
261
|
+
view.emitDragChangeEvent(point?.x?.toFloat() ?: 0f, point?.y?.toFloat() ?: 0f)
|
|
262
|
+
if (!view.rasterize) positionLiveMarker(view)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
override fun onMarkerDragEnd(marker: Marker) {
|
|
267
|
+
markerToViewMap[marker]?.let { view ->
|
|
268
|
+
view.isDragging = false
|
|
269
|
+
view.setCoordinate(marker.position.latitude, marker.position.longitude)
|
|
270
|
+
val point = googleMap?.projection?.toScreenLocation(marker.position)
|
|
271
|
+
view.emitDragEndEvent(point?.x?.toFloat() ?: 0f, point?.y?.toFloat() ?: 0f)
|
|
272
|
+
if (!view.rasterize) positionLiveMarker(view)
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
override fun getInfoWindow(marker: Marker): View? {
|
|
277
|
+
// Non-bubbled callouts are rendered as live views, not info windows
|
|
278
|
+
return null
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
override fun getInfoContents(marker: Marker): View? {
|
|
282
|
+
val markerView = markerToViewMap[marker] ?: return null
|
|
283
|
+
val calloutView = markerView.calloutView ?: return null
|
|
284
|
+
if (!calloutView.hasCustomContent || !calloutView.bubbled) return null
|
|
285
|
+
|
|
286
|
+
val bitmap = calloutView.createContentBitmap() ?: return null
|
|
287
|
+
return ImageView(context).apply { setImageBitmap(bitmap) }
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
private fun showNonBubbledCallout(marker: Marker, calloutView: LuggCalloutView) {
|
|
291
|
+
val wrapper = wrapperView ?: return
|
|
292
|
+
val contentView = calloutView.contentView
|
|
293
|
+
|
|
294
|
+
calloutView.onUpdate = {
|
|
295
|
+
layoutNonBubbledCallout()
|
|
296
|
+
positionNonBubbledCallout()
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
dismissInfoWindows()
|
|
300
|
+
wrapper.addView(contentView)
|
|
301
|
+
activeNonBubbledMarker = marker
|
|
302
|
+
layoutNonBubbledCallout()
|
|
303
|
+
positionNonBubbledCallout()
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private fun dismissInfoWindows() {
|
|
307
|
+
for ((marker, _) in markerToViewMap) {
|
|
308
|
+
if (marker.isInfoWindowShown) {
|
|
309
|
+
marker.hideInfoWindow()
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private fun dismissNonBubbledCallout() {
|
|
315
|
+
val marker = activeNonBubbledMarker ?: return
|
|
316
|
+
val markerView = markerToViewMap[marker] ?: return
|
|
317
|
+
val calloutView = markerView.calloutView ?: return
|
|
318
|
+
val contentView = calloutView.contentView
|
|
319
|
+
|
|
320
|
+
calloutView.onUpdate = null
|
|
321
|
+
(contentView.parent as? android.view.ViewGroup)?.removeView(contentView)
|
|
322
|
+
activeNonBubbledMarker = null
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
private fun layoutNonBubbledCallout() {
|
|
326
|
+
val marker = activeNonBubbledMarker ?: return
|
|
327
|
+
val markerView = markerToViewMap[marker] ?: return
|
|
328
|
+
val calloutView = markerView.calloutView ?: return
|
|
329
|
+
val contentView = calloutView.contentView
|
|
330
|
+
|
|
331
|
+
var contentWidth = 0
|
|
332
|
+
var contentHeight = 0
|
|
333
|
+
for (i in 0 until contentView.childCount) {
|
|
334
|
+
val child = contentView.getChildAt(i)
|
|
335
|
+
val childRight = child.left + child.width
|
|
336
|
+
val childBottom = child.top + child.height
|
|
337
|
+
if (childRight > contentWidth) contentWidth = childRight
|
|
338
|
+
if (childBottom > contentHeight) contentHeight = childBottom
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
contentView.measure(
|
|
342
|
+
View.MeasureSpec.makeMeasureSpec(contentWidth, View.MeasureSpec.EXACTLY),
|
|
343
|
+
View.MeasureSpec.makeMeasureSpec(contentHeight, View.MeasureSpec.EXACTLY)
|
|
344
|
+
)
|
|
345
|
+
contentView.layout(0, 0, contentWidth, contentHeight)
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
private fun positionNonBubbledCallout() {
|
|
349
|
+
val marker = activeNonBubbledMarker ?: return
|
|
350
|
+
val markerView = markerToViewMap[marker] ?: return
|
|
351
|
+
val calloutView = markerView.calloutView ?: return
|
|
352
|
+
val contentView = calloutView.contentView
|
|
353
|
+
val map = googleMap ?: return
|
|
354
|
+
|
|
355
|
+
val point = map.projection.toScreenLocation(marker.position)
|
|
356
|
+
contentView.translationX = point.x - contentView.width * calloutView.anchorX
|
|
357
|
+
contentView.translationY = point.y - contentView.height * calloutView.anchorY
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// endregion
|
|
361
|
+
|
|
362
|
+
// region Props
|
|
363
|
+
|
|
364
|
+
override fun setZoomEnabled(enabled: Boolean) {
|
|
365
|
+
zoomEnabled = enabled
|
|
366
|
+
googleMap?.uiSettings?.isZoomGesturesEnabled = enabled
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
override fun setScrollEnabled(enabled: Boolean) {
|
|
370
|
+
scrollEnabled = enabled
|
|
371
|
+
googleMap?.uiSettings?.isScrollGesturesEnabled = enabled
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
override fun setRotateEnabled(enabled: Boolean) {
|
|
375
|
+
rotateEnabled = enabled
|
|
376
|
+
googleMap?.uiSettings?.isRotateGesturesEnabled = enabled
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
override fun setPitchEnabled(enabled: Boolean) {
|
|
380
|
+
pitchEnabled = enabled
|
|
381
|
+
googleMap?.uiSettings?.isTiltGesturesEnabled = enabled
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
@SuppressLint("MissingPermission")
|
|
385
|
+
override fun setUserLocationEnabled(enabled: Boolean) {
|
|
386
|
+
userLocationEnabled = enabled
|
|
387
|
+
val hasPermission =
|
|
388
|
+
context.checkSelfPermission(
|
|
389
|
+
android.Manifest.permission.ACCESS_FINE_LOCATION
|
|
390
|
+
) == android.content.pm.PackageManager.PERMISSION_GRANTED ||
|
|
391
|
+
context.checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) ==
|
|
392
|
+
android.content.pm.PackageManager.PERMISSION_GRANTED
|
|
393
|
+
googleMap?.isMyLocationEnabled = userLocationEnabled && hasPermission
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
override fun setUserLocationButtonEnabled(enabled: Boolean) {
|
|
397
|
+
userLocationButtonEnabled = enabled
|
|
398
|
+
googleMap?.uiSettings?.isMyLocationButtonEnabled = enabled
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
override fun setTheme(value: String) {
|
|
402
|
+
theme = value
|
|
403
|
+
applyTheme()
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
override fun setMinZoom(zoom: Double) {
|
|
407
|
+
minZoom = if (zoom > 0) zoom.toFloat() else null
|
|
408
|
+
googleMap?.let { map ->
|
|
409
|
+
minZoom?.let { map.setMinZoomPreference(it) } ?: map.resetMinMaxZoomPreference()
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
override fun setMaxZoom(zoom: Double) {
|
|
414
|
+
maxZoom = if (zoom > 0) zoom.toFloat() else null
|
|
415
|
+
googleMap?.let { map ->
|
|
416
|
+
maxZoom?.let { map.setMaxZoomPreference(it) } ?: map.resetMinMaxZoomPreference()
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
override fun setEdgeInsets(edgeInsets: EdgeInsets) {
|
|
421
|
+
val oldInsets = this.edgeInsets
|
|
422
|
+
this.edgeInsets = edgeInsets
|
|
423
|
+
applyEdgeInsets()
|
|
424
|
+
|
|
425
|
+
val map = googleMap
|
|
426
|
+
if (map != null && oldInsets != edgeInsets) {
|
|
427
|
+
mapView?.post {
|
|
428
|
+
setEdgeInsets(edgeInsets, 0)
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
override fun setEdgeInsets(edgeInsets: EdgeInsets, duration: Int) {
|
|
434
|
+
val map = googleMap
|
|
435
|
+
val oldInsets = this.edgeInsets
|
|
436
|
+
this.edgeInsets = edgeInsets
|
|
437
|
+
|
|
438
|
+
if (map != null && oldInsets != edgeInsets) {
|
|
439
|
+
val cameraUpdate = CameraUpdateFactory.newCameraPosition(map.cameraPosition)
|
|
440
|
+
applyEdgeInsets()
|
|
441
|
+
when {
|
|
442
|
+
duration < 0 -> map.animateCamera(cameraUpdate)
|
|
443
|
+
duration > 0 -> map.animateCamera(cameraUpdate, duration, null)
|
|
444
|
+
else -> map.moveCamera(cameraUpdate)
|
|
445
|
+
}
|
|
446
|
+
} else {
|
|
447
|
+
applyEdgeInsets()
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// endregion
|
|
452
|
+
|
|
453
|
+
// region MarkerViewDelegate
|
|
454
|
+
|
|
455
|
+
override fun markerViewDidLayout(markerView: LuggMarkerView) {
|
|
456
|
+
if (googleMap == null) {
|
|
457
|
+
pendingMarkerViews.add(markerView)
|
|
458
|
+
return
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (markerView.hasCustomView) {
|
|
462
|
+
markerView.updateIcon { addMarkerViewToMap(markerView) }
|
|
463
|
+
} else {
|
|
464
|
+
syncMarkerView(markerView)
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
override fun markerViewDidUpdate(markerView: LuggMarkerView) {
|
|
469
|
+
syncMarkerView(markerView)
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// endregion
|
|
473
|
+
|
|
474
|
+
// region PolylineViewDelegate
|
|
475
|
+
|
|
476
|
+
override fun polylineViewDidUpdate(polylineView: LuggPolylineView) {
|
|
477
|
+
syncPolylineView(polylineView)
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// endregion
|
|
481
|
+
|
|
482
|
+
// region PolygonViewDelegate
|
|
483
|
+
|
|
484
|
+
override fun polygonViewDidUpdate(polygonView: LuggPolygonView) {
|
|
485
|
+
syncPolygonView(polygonView)
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// endregion
|
|
489
|
+
|
|
490
|
+
// region Marker Management
|
|
491
|
+
|
|
492
|
+
override fun addMarkerView(markerView: LuggMarkerView) {
|
|
493
|
+
markerView.delegate = this
|
|
494
|
+
syncMarkerView(markerView)
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
override fun removeMarkerView(markerView: LuggMarkerView) {
|
|
498
|
+
removeLiveMarker(markerView)
|
|
499
|
+
markerView.marker?.let { markerToViewMap.remove(it) }
|
|
500
|
+
markerView.marker?.remove()
|
|
501
|
+
markerView.marker = null
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
private fun syncMarkerView(markerView: LuggMarkerView) {
|
|
505
|
+
if (googleMap == null) {
|
|
506
|
+
pendingMarkerViews.add(markerView)
|
|
507
|
+
return
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
if (markerView.marker == null) {
|
|
511
|
+
if (markerView.hasCustomView) return
|
|
512
|
+
addMarkerViewToMap(markerView)
|
|
513
|
+
return
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
markerView.marker?.apply {
|
|
517
|
+
if (!markerView.isDragging) {
|
|
518
|
+
position = LatLng(markerView.latitude, markerView.longitude)
|
|
519
|
+
}
|
|
520
|
+
title = markerView.title
|
|
521
|
+
snippet = markerView.description
|
|
522
|
+
setAnchor(markerView.anchorX, markerView.anchorY)
|
|
523
|
+
zIndex = markerView.zIndex
|
|
524
|
+
rotation = markerView.rotate
|
|
525
|
+
isDraggable = markerView.draggable
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (markerView.hasCustomView) {
|
|
529
|
+
if (markerView.scaleChanged) {
|
|
530
|
+
markerView.applyScaleToMarker()
|
|
531
|
+
markerView.clearScaleChanged()
|
|
532
|
+
}
|
|
533
|
+
if (!markerView.rasterize) {
|
|
534
|
+
positionLiveMarker(markerView)
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
private fun processPendingMarkers() {
|
|
540
|
+
if (googleMap == null) return
|
|
541
|
+
pendingMarkerViews.forEach { addMarkerViewToMap(it) }
|
|
542
|
+
pendingMarkerViews.clear()
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
private fun addMarkerViewToMap(markerView: LuggMarkerView) {
|
|
546
|
+
val map = googleMap ?: return
|
|
547
|
+
|
|
548
|
+
val position = LatLng(markerView.latitude, markerView.longitude)
|
|
549
|
+
val options = AdvancedMarkerOptions()
|
|
550
|
+
.position(position)
|
|
551
|
+
.title(markerView.title)
|
|
552
|
+
.snippet(markerView.description)
|
|
553
|
+
|
|
554
|
+
val marker = map.addMarker(options) as AdvancedMarker
|
|
555
|
+
marker.setAnchor(markerView.anchorX, markerView.anchorY)
|
|
556
|
+
marker.zIndex = markerView.zIndex
|
|
557
|
+
marker.rotation = markerView.rotate
|
|
558
|
+
marker.isDraggable = markerView.draggable
|
|
559
|
+
|
|
560
|
+
markerView.marker = marker
|
|
561
|
+
markerToViewMap[marker] = markerView
|
|
562
|
+
|
|
563
|
+
if (markerView.hasCustomView) {
|
|
564
|
+
if (markerView.rasterize) {
|
|
565
|
+
markerView.applyIconToMarker()
|
|
566
|
+
} else {
|
|
567
|
+
showLiveMarker(markerView)
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Workaround: AdvancedMarker.iconView is buggy on Android, so we manually add the custom
|
|
573
|
+
// content view to the wrapper and position it via screen projection instead. The underlying
|
|
574
|
+
// marker uses a transparent bitmap matching the content size so taps still trigger onMarkerClick.
|
|
575
|
+
private fun showLiveMarker(markerView: LuggMarkerView) {
|
|
576
|
+
val wrapper = wrapperView ?: return
|
|
577
|
+
|
|
578
|
+
markerView.onUpdate = {
|
|
579
|
+
updateLiveMarkerHitArea(markerView)
|
|
580
|
+
positionLiveMarker(markerView)
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
val contentView = markerView.contentView
|
|
584
|
+
contentView.pointerEvents = com.facebook.react.uimanager.PointerEvents.NONE
|
|
585
|
+
(contentView.parent as? android.view.ViewGroup)?.removeView(contentView)
|
|
586
|
+
wrapper.addView(contentView)
|
|
587
|
+
liveMarkerViews.add(markerView)
|
|
588
|
+
markerView.layoutContentView()
|
|
589
|
+
updateLiveMarkerHitArea(markerView)
|
|
590
|
+
positionLiveMarker(markerView)
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
private fun updateLiveMarkerHitArea(markerView: LuggMarkerView) {
|
|
594
|
+
val marker = markerView.marker ?: return
|
|
595
|
+
val contentView = markerView.contentView
|
|
596
|
+
val w = contentView.width.coerceAtLeast(1)
|
|
597
|
+
val h = contentView.height.coerceAtLeast(1)
|
|
598
|
+
marker.setIcon(BitmapDescriptorFactory.fromBitmap(createBitmap(w, h)))
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
private fun removeLiveMarker(markerView: LuggMarkerView) {
|
|
602
|
+
markerView.onUpdate = null
|
|
603
|
+
val contentView = markerView.contentView
|
|
604
|
+
(contentView.parent as? android.view.ViewGroup)?.removeView(contentView)
|
|
605
|
+
liveMarkerViews.remove(markerView)
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
private fun positionLiveMarkers() {
|
|
609
|
+
for (markerView in liveMarkerViews) {
|
|
610
|
+
positionLiveMarker(markerView)
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
private fun positionLiveMarker(markerView: LuggMarkerView) {
|
|
615
|
+
val map = googleMap ?: return
|
|
616
|
+
val contentView = markerView.contentView
|
|
617
|
+
val point = map.projection.toScreenLocation(LatLng(markerView.latitude, markerView.longitude))
|
|
618
|
+
contentView.translationX = point.x - contentView.width * markerView.anchorX
|
|
619
|
+
contentView.translationY = point.y - contentView.height * markerView.anchorY
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// endregion
|
|
623
|
+
|
|
624
|
+
// region Polyline Management
|
|
625
|
+
|
|
626
|
+
override fun addPolylineView(polylineView: LuggPolylineView) {
|
|
627
|
+
polylineView.delegate = this
|
|
628
|
+
syncPolylineView(polylineView)
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
override fun removePolylineView(polylineView: LuggPolylineView) {
|
|
632
|
+
polylineAnimators[polylineView]?.destroy()
|
|
633
|
+
polylineAnimators.remove(polylineView)
|
|
634
|
+
polylineView.polyline?.remove()
|
|
635
|
+
polylineView.polyline = null
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
private fun syncPolylineView(polylineView: LuggPolylineView) {
|
|
639
|
+
if (googleMap == null) {
|
|
640
|
+
pendingPolylineViews.add(polylineView)
|
|
641
|
+
return
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
if (polylineView.polyline == null) {
|
|
645
|
+
addPolylineViewToMap(polylineView)
|
|
646
|
+
return
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
polylineView.polyline?.width = polylineView.strokeWidth.dpToPx()
|
|
650
|
+
polylineView.polyline?.zIndex = polylineView.zIndex
|
|
651
|
+
|
|
652
|
+
polylineAnimators[polylineView]?.apply {
|
|
653
|
+
coordinates = polylineView.coordinates
|
|
654
|
+
strokeColors = polylineView.strokeColors
|
|
655
|
+
strokeWidth = polylineView.strokeWidth.dpToPx()
|
|
656
|
+
animatedOptions = polylineView.animatedOptions
|
|
657
|
+
animated = polylineView.animated
|
|
658
|
+
update()
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
private fun processPendingPolylines() {
|
|
663
|
+
if (googleMap == null) return
|
|
664
|
+
pendingPolylineViews.forEach { addPolylineViewToMap(it) }
|
|
665
|
+
pendingPolylineViews.clear()
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
private fun addPolylineViewToMap(polylineView: LuggPolylineView) {
|
|
669
|
+
val map = googleMap ?: return
|
|
670
|
+
|
|
671
|
+
val options = PolylineOptions()
|
|
672
|
+
.width(polylineView.strokeWidth.dpToPx())
|
|
673
|
+
.zIndex(polylineView.zIndex)
|
|
674
|
+
|
|
675
|
+
val polyline = map.addPolyline(options)
|
|
676
|
+
polylineView.polyline = polyline
|
|
677
|
+
|
|
678
|
+
val animator = PolylineAnimator().apply {
|
|
679
|
+
this.polyline = polyline
|
|
680
|
+
coordinates = polylineView.coordinates
|
|
681
|
+
strokeColors = polylineView.strokeColors
|
|
682
|
+
strokeWidth = polylineView.strokeWidth.dpToPx()
|
|
683
|
+
animatedOptions = polylineView.animatedOptions
|
|
684
|
+
animated = polylineView.animated
|
|
685
|
+
update()
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
polylineAnimators[polylineView] = animator
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// endregion
|
|
692
|
+
|
|
693
|
+
// region Polygon Management
|
|
694
|
+
|
|
695
|
+
override fun addPolygonView(polygonView: LuggPolygonView) {
|
|
696
|
+
polygonView.delegate = this
|
|
697
|
+
syncPolygonView(polygonView)
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
override fun removePolygonView(polygonView: LuggPolygonView) {
|
|
701
|
+
polygonView.polygon?.let { polygonToViewMap.remove(it) }
|
|
702
|
+
polygonView.polygon?.remove()
|
|
703
|
+
polygonView.polygon = null
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
private fun syncPolygonView(polygonView: LuggPolygonView) {
|
|
707
|
+
if (googleMap == null) {
|
|
708
|
+
pendingPolygonViews.add(polygonView)
|
|
709
|
+
return
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
if (polygonView.polygon == null) {
|
|
713
|
+
addPolygonViewToMap(polygonView)
|
|
714
|
+
return
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
polygonView.polygon?.apply {
|
|
718
|
+
points = polygonView.coordinates
|
|
719
|
+
holes = polygonView.holes
|
|
720
|
+
fillColor = polygonView.fillColor
|
|
721
|
+
strokeColor = polygonView.strokeColor
|
|
722
|
+
strokeWidth = polygonView.strokeWidth.dpToPx()
|
|
723
|
+
zIndex = polygonView.zIndex
|
|
724
|
+
isClickable = true
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
private fun processPendingPolygons() {
|
|
729
|
+
if (googleMap == null) return
|
|
730
|
+
pendingPolygonViews.forEach { addPolygonViewToMap(it) }
|
|
731
|
+
pendingPolygonViews.clear()
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
private fun addPolygonViewToMap(polygonView: LuggPolygonView) {
|
|
735
|
+
val map = googleMap ?: return
|
|
736
|
+
|
|
737
|
+
val options = PolygonOptions()
|
|
738
|
+
.addAll(polygonView.coordinates)
|
|
739
|
+
.fillColor(polygonView.fillColor)
|
|
740
|
+
.strokeColor(polygonView.strokeColor)
|
|
741
|
+
.strokeWidth(polygonView.strokeWidth.dpToPx())
|
|
742
|
+
.zIndex(polygonView.zIndex)
|
|
743
|
+
.clickable(true)
|
|
744
|
+
|
|
745
|
+
for (hole in polygonView.holes) {
|
|
746
|
+
options.addHole(hole)
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
val polygon = map.addPolygon(options)
|
|
750
|
+
polygonView.polygon = polygon
|
|
751
|
+
polygonToViewMap[polygon] = polygonView
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
// endregion
|
|
755
|
+
|
|
756
|
+
// region Lifecycle
|
|
757
|
+
|
|
758
|
+
override fun pauseAnimations() {
|
|
759
|
+
polylineAnimators.values.forEach { it.pause() }
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
override fun resumeAnimations() {
|
|
763
|
+
polylineAnimators.values.forEach { it.resume() }
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// endregion
|
|
767
|
+
|
|
768
|
+
// region Commands
|
|
769
|
+
|
|
770
|
+
override fun moveCamera(latitude: Double, longitude: Double, zoom: Double, duration: Int) {
|
|
771
|
+
val map = googleMap ?: return
|
|
772
|
+
val position = LatLng(latitude, longitude)
|
|
773
|
+
val targetZoom = if (zoom > 0) zoom.toFloat() else map.cameraPosition.zoom
|
|
774
|
+
val cameraUpdate = CameraUpdateFactory.newLatLngZoom(position, targetZoom)
|
|
775
|
+
when {
|
|
776
|
+
duration < 0 -> map.animateCamera(cameraUpdate)
|
|
777
|
+
duration > 0 -> map.animateCamera(cameraUpdate, duration, null)
|
|
778
|
+
else -> map.moveCamera(cameraUpdate)
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
override fun fitCoordinates(
|
|
783
|
+
coordinates: List<Any>,
|
|
784
|
+
edgeInsetsTop: Int,
|
|
785
|
+
edgeInsetsLeft: Int,
|
|
786
|
+
edgeInsetsBottom: Int,
|
|
787
|
+
edgeInsetsRight: Int,
|
|
788
|
+
duration: Int
|
|
789
|
+
) {
|
|
790
|
+
val map = googleMap ?: return
|
|
791
|
+
if (coordinates.isEmpty()) return
|
|
792
|
+
|
|
793
|
+
val latLngs = coordinates.filterIsInstance<LatLng>()
|
|
794
|
+
if (latLngs.isEmpty()) return
|
|
795
|
+
|
|
796
|
+
val boundsBuilder = com.google.android.gms.maps.model.LatLngBounds.Builder()
|
|
797
|
+
latLngs.forEach { boundsBuilder.include(it) }
|
|
798
|
+
val bounds = boundsBuilder.build()
|
|
799
|
+
|
|
800
|
+
val top = edgeInsetsTop.toFloat().dpToPx().toInt()
|
|
801
|
+
val left = edgeInsetsLeft.toFloat().dpToPx().toInt()
|
|
802
|
+
val bottom = edgeInsetsBottom.toFloat().dpToPx().toInt()
|
|
803
|
+
val right = edgeInsetsRight.toFloat().dpToPx().toInt()
|
|
804
|
+
|
|
805
|
+
map.setPadding(
|
|
806
|
+
edgeInsets.left + left,
|
|
807
|
+
edgeInsets.top + top,
|
|
808
|
+
edgeInsets.right + right,
|
|
809
|
+
edgeInsets.bottom + bottom
|
|
810
|
+
)
|
|
811
|
+
|
|
812
|
+
val cameraUpdate = CameraUpdateFactory.newLatLngBounds(bounds, 0)
|
|
813
|
+
|
|
814
|
+
when {
|
|
815
|
+
duration < 0 -> map.animateCamera(cameraUpdate)
|
|
816
|
+
duration > 0 -> map.animateCamera(cameraUpdate, duration, null)
|
|
817
|
+
else -> map.moveCamera(cameraUpdate)
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
map.setPadding(edgeInsets.left, edgeInsets.top, edgeInsets.right, edgeInsets.bottom)
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// endregion
|
|
824
|
+
|
|
825
|
+
// region Private
|
|
826
|
+
|
|
827
|
+
private fun applyUiSettings() {
|
|
828
|
+
googleMap?.uiSettings?.apply {
|
|
829
|
+
isZoomGesturesEnabled = zoomEnabled
|
|
830
|
+
isScrollGesturesEnabled = scrollEnabled
|
|
831
|
+
isRotateGesturesEnabled = rotateEnabled
|
|
832
|
+
isTiltGesturesEnabled = pitchEnabled
|
|
833
|
+
isMyLocationButtonEnabled = userLocationButtonEnabled
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
private fun applyZoomLimits() {
|
|
838
|
+
googleMap?.apply {
|
|
839
|
+
minZoom?.let { setMinZoomPreference(it) }
|
|
840
|
+
maxZoom?.let { setMaxZoomPreference(it) }
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
private fun applyEdgeInsets() {
|
|
845
|
+
googleMap?.setPadding(edgeInsets.left, edgeInsets.top, edgeInsets.right, edgeInsets.bottom)
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
private fun applyTheme() {
|
|
849
|
+
val colorScheme = when (theme) {
|
|
850
|
+
"dark" -> MapColorScheme.DARK
|
|
851
|
+
"light" -> MapColorScheme.LIGHT
|
|
852
|
+
else -> MapColorScheme.FOLLOW_SYSTEM
|
|
853
|
+
}
|
|
854
|
+
googleMap?.setMapColorScheme(colorScheme)
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
@SuppressLint("MissingPermission")
|
|
858
|
+
private fun applyUserLocation() {
|
|
859
|
+
val hasPermission =
|
|
860
|
+
context.checkSelfPermission(
|
|
861
|
+
android.Manifest.permission.ACCESS_FINE_LOCATION
|
|
862
|
+
) == android.content.pm.PackageManager.PERMISSION_GRANTED ||
|
|
863
|
+
context.checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) ==
|
|
864
|
+
android.content.pm.PackageManager.PERMISSION_GRANTED
|
|
865
|
+
googleMap?.isMyLocationEnabled = userLocationEnabled && hasPermission
|
|
866
|
+
googleMap?.uiSettings?.isMyLocationButtonEnabled = userLocationButtonEnabled
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
// endregion
|
|
870
|
+
|
|
871
|
+
companion object {
|
|
872
|
+
const val DEMO_MAP_ID = "DEMO_MAP_ID"
|
|
873
|
+
}
|
|
874
|
+
}
|