@lugg/maps 1.0.0-beta.0 → 1.0.0-beta.10
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 +4 -1
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/luggmaps/LuggCalloutView.kt +79 -0
- package/android/src/main/java/com/luggmaps/LuggCalloutViewManager.kt +39 -0
- package/android/src/main/java/com/luggmaps/LuggCircleView.kt +85 -0
- package/android/src/main/java/com/luggmaps/LuggCircleViewManager.kt +79 -0
- package/android/src/main/java/com/luggmaps/LuggGroundOverlayView.kt +81 -0
- package/android/src/main/java/com/luggmaps/LuggGroundOverlayViewManager.kt +82 -0
- package/android/src/main/java/com/luggmaps/LuggMapView.kt +49 -0
- package/android/src/main/java/com/luggmaps/LuggMapViewManager.kt +31 -0
- package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +0 -11
- package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +99 -51
- package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +13 -0
- package/android/src/main/java/com/luggmaps/LuggPackage.kt +11 -1
- package/android/src/main/java/com/luggmaps/LuggPolylineView.kt +1 -22
- package/android/src/main/java/com/luggmaps/LuggTileOverlayView.kt +92 -0
- package/android/src/main/java/com/luggmaps/LuggTileOverlayViewManager.kt +80 -0
- package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +628 -18
- package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +14 -0
- package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +12 -7
- package/android/src/main/java/com/luggmaps/events/CirclePressEvent.kt +12 -0
- package/android/src/main/java/com/luggmaps/events/GroundOverlayPressEvent.kt +12 -0
- package/android/src/main/java/com/luggmaps/events/TileOverlayPressEvent.kt +12 -0
- package/android/src/main/java/com/luggmaps/extensions/ViewExtensions.kt +11 -0
- package/ios/LuggCalloutView.h +23 -0
- package/ios/LuggCalloutView.mm +155 -0
- package/ios/LuggCircleView.h +31 -0
- package/ios/LuggCircleView.mm +133 -0
- package/ios/LuggGroundOverlayView.h +30 -0
- package/ios/LuggGroundOverlayView.mm +125 -0
- package/ios/LuggMapView.mm +84 -2
- package/ios/LuggMarkerView.h +5 -0
- package/ios/LuggMarkerView.mm +40 -2
- package/ios/LuggTileOverlayView.h +31 -0
- package/ios/LuggTileOverlayView.mm +130 -0
- package/ios/core/AppleMapProvider.mm +838 -34
- package/ios/core/GMSPolylineAnimator.m +6 -3
- package/ios/core/GoogleMapProvider.mm +506 -19
- package/ios/core/LuggAnnotationView.h +12 -0
- package/ios/core/LuggAnnotationView.mm +55 -0
- package/ios/core/MapProviderDelegate.h +20 -1
- package/ios/events/CirclePressEvent.h +20 -0
- package/ios/events/GroundOverlayPressEvent.h +20 -0
- package/ios/events/TileOverlayPressEvent.h +20 -0
- package/lib/module/MapProvider.web.js +7 -2
- package/lib/module/MapProvider.web.js.map +1 -1
- package/lib/module/MapView.js +12 -1
- package/lib/module/MapView.js.map +1 -1
- package/lib/module/MapView.web.js +36 -20
- package/lib/module/MapView.web.js.map +1 -1
- package/lib/module/components/Circle.js +46 -0
- package/lib/module/components/Circle.js.map +1 -0
- package/lib/module/components/Circle.types.js +4 -0
- package/lib/module/components/Circle.types.js.map +1 -0
- package/lib/module/components/Circle.web.js +79 -0
- package/lib/module/components/Circle.web.js.map +1 -0
- package/lib/module/components/GeoJson.js +3 -3
- package/lib/module/components/GeoJson.js.map +1 -1
- package/lib/module/components/GroundOverlay.js +45 -0
- package/lib/module/components/GroundOverlay.js.map +1 -0
- package/lib/module/components/GroundOverlay.types.js +4 -0
- package/lib/module/components/GroundOverlay.types.js.map +1 -0
- package/lib/module/components/GroundOverlay.web.js +77 -0
- package/lib/module/components/GroundOverlay.web.js.map +1 -0
- package/lib/module/components/Marker.js +41 -6
- package/lib/module/components/Marker.js.map +1 -1
- package/lib/module/components/Marker.web.js +103 -26
- package/lib/module/components/Marker.web.js.map +1 -1
- package/lib/module/components/Polygon.web.js +3 -3
- package/lib/module/components/Polygon.web.js.map +1 -1
- package/lib/module/components/Polyline.web.js +6 -12
- package/lib/module/components/Polyline.web.js.map +1 -1
- package/lib/module/components/TileOverlay.js +44 -0
- package/lib/module/components/TileOverlay.js.map +1 -0
- package/lib/module/components/TileOverlay.types.js +4 -0
- package/lib/module/components/TileOverlay.types.js.map +1 -0
- package/lib/module/components/TileOverlay.web.js +69 -0
- package/lib/module/components/TileOverlay.web.js.map +1 -0
- package/lib/module/components/index.js +3 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/components/index.web.js +3 -0
- package/lib/module/components/index.web.js.map +1 -1
- package/lib/module/fabric/LuggCalloutViewNativeComponent.ts +20 -0
- package/lib/module/fabric/LuggCircleViewNativeComponent.ts +25 -0
- package/lib/module/fabric/LuggGroundOverlayViewNativeComponent.ts +29 -0
- package/lib/module/fabric/LuggMapViewNativeComponent.ts +13 -5
- package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +14 -2
- package/lib/module/fabric/LuggTileOverlayViewNativeComponent.ts +30 -0
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +3 -0
- package/lib/module/index.web.js.map +1 -1
- package/lib/typescript/src/MapProvider.web.d.ts +9 -2
- package/lib/typescript/src/MapProvider.web.d.ts.map +1 -1
- package/lib/typescript/src/MapView.d.ts +1 -1
- package/lib/typescript/src/MapView.d.ts.map +1 -1
- package/lib/typescript/src/MapView.types.d.ts +36 -1
- package/lib/typescript/src/MapView.types.d.ts.map +1 -1
- package/lib/typescript/src/MapView.web.d.ts +1 -1
- package/lib/typescript/src/MapView.web.d.ts.map +1 -1
- package/lib/typescript/src/components/Circle.d.ts +10 -0
- package/lib/typescript/src/components/Circle.d.ts.map +1 -0
- package/lib/typescript/src/components/Circle.types.d.ts +33 -0
- package/lib/typescript/src/components/Circle.types.d.ts.map +1 -0
- package/lib/typescript/src/components/Circle.web.d.ts +3 -0
- package/lib/typescript/src/components/Circle.web.d.ts.map +1 -0
- package/lib/typescript/src/components/GeoJson.d.ts +2 -1
- package/lib/typescript/src/components/GeoJson.d.ts.map +1 -1
- package/lib/typescript/src/components/GeoJson.types.d.ts +11 -1
- package/lib/typescript/src/components/GeoJson.types.d.ts.map +1 -1
- package/lib/typescript/src/components/GroundOverlay.d.ts +10 -0
- package/lib/typescript/src/components/GroundOverlay.d.ts.map +1 -0
- package/lib/typescript/src/components/GroundOverlay.types.d.ts +35 -0
- package/lib/typescript/src/components/GroundOverlay.types.d.ts.map +1 -0
- package/lib/typescript/src/components/GroundOverlay.web.d.ts +3 -0
- package/lib/typescript/src/components/GroundOverlay.web.d.ts.map +1 -0
- package/lib/typescript/src/components/Marker.d.ts +6 -3
- package/lib/typescript/src/components/Marker.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.types.d.ts +40 -2
- package/lib/typescript/src/components/Marker.types.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.web.d.ts +3 -2
- package/lib/typescript/src/components/Marker.web.d.ts.map +1 -1
- package/lib/typescript/src/components/Polygon.web.d.ts +1 -1
- package/lib/typescript/src/components/Polygon.web.d.ts.map +1 -1
- package/lib/typescript/src/components/Polyline.web.d.ts +1 -1
- package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -1
- package/lib/typescript/src/components/TileOverlay.d.ts +10 -0
- package/lib/typescript/src/components/TileOverlay.d.ts.map +1 -0
- package/lib/typescript/src/components/TileOverlay.types.d.ts +36 -0
- package/lib/typescript/src/components/TileOverlay.types.d.ts.map +1 -0
- package/lib/typescript/src/components/TileOverlay.web.d.ts +3 -0
- package/lib/typescript/src/components/TileOverlay.web.d.ts.map +1 -0
- package/lib/typescript/src/components/index.d.ts +7 -1
- package/lib/typescript/src/components/index.d.ts.map +1 -1
- package/lib/typescript/src/components/index.web.d.ts +7 -1
- 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/LuggCircleViewNativeComponent.d.ts +18 -0
- package/lib/typescript/src/fabric/LuggCircleViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/LuggGroundOverlayViewNativeComponent.d.ts +21 -0
- package/lib/typescript/src/fabric/LuggGroundOverlayViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts +10 -5
- package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +8 -1
- package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/fabric/LuggTileOverlayViewNativeComponent.d.ts +21 -0
- package/lib/typescript/src/fabric/LuggTileOverlayViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +10 -4
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +9 -3
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +0 -4
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +6 -2
- package/src/MapProvider.web.tsx +15 -3
- package/src/MapView.tsx +12 -1
- package/src/MapView.types.ts +118 -1
- package/src/MapView.web.tsx +379 -322
- package/src/components/Circle.tsx +52 -0
- package/src/components/Circle.types.ts +33 -0
- package/src/components/Circle.web.tsx +95 -0
- package/src/components/GeoJson.tsx +3 -3
- package/src/components/GeoJson.types.ts +12 -1
- package/src/components/GroundOverlay.tsx +47 -0
- package/src/components/GroundOverlay.types.ts +36 -0
- package/src/components/GroundOverlay.web.tsx +81 -0
- package/src/components/Marker.tsx +59 -5
- package/src/components/Marker.types.ts +42 -2
- package/src/components/Marker.web.tsx +235 -99
- package/src/components/Polygon.web.tsx +93 -89
- package/src/components/Polyline.web.tsx +235 -235
- package/src/components/TileOverlay.tsx +44 -0
- package/src/components/TileOverlay.types.ts +37 -0
- package/src/components/TileOverlay.web.tsx +97 -0
- package/src/components/index.ts +11 -0
- package/src/components/index.web.ts +10 -1
- package/src/fabric/LuggCalloutViewNativeComponent.ts +20 -0
- package/src/fabric/LuggCircleViewNativeComponent.ts +25 -0
- package/src/fabric/LuggGroundOverlayViewNativeComponent.ts +29 -0
- package/src/fabric/LuggMapViewNativeComponent.ts +13 -5
- package/src/fabric/LuggMarkerViewNativeComponent.ts +14 -2
- package/src/fabric/LuggTileOverlayViewNativeComponent.ts +30 -0
- package/src/index.ts +14 -1
- package/src/index.web.ts +17 -1
- package/src/types.ts +0 -5
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
package com.luggmaps.core
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.ComponentCallbacks2
|
|
4
5
|
import android.content.Context
|
|
6
|
+
import android.content.res.Configuration
|
|
5
7
|
import android.view.View
|
|
8
|
+
import android.widget.ImageView
|
|
9
|
+
import androidx.core.graphics.createBitmap
|
|
10
|
+
import androidx.core.view.ViewCompat
|
|
11
|
+
import androidx.core.view.WindowInsetsCompat
|
|
6
12
|
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
7
13
|
import com.google.android.gms.maps.CameraUpdateFactory
|
|
8
14
|
import com.google.android.gms.maps.GoogleMap
|
|
@@ -11,12 +17,25 @@ import com.google.android.gms.maps.MapView
|
|
|
11
17
|
import com.google.android.gms.maps.OnMapReadyCallback
|
|
12
18
|
import com.google.android.gms.maps.model.AdvancedMarker
|
|
13
19
|
import com.google.android.gms.maps.model.AdvancedMarkerOptions
|
|
20
|
+
import com.google.android.gms.maps.model.BitmapDescriptorFactory
|
|
21
|
+
import com.google.android.gms.maps.model.Circle
|
|
22
|
+
import com.google.android.gms.maps.model.CircleOptions
|
|
23
|
+
import com.google.android.gms.maps.model.GroundOverlay
|
|
24
|
+
import com.google.android.gms.maps.model.GroundOverlayOptions
|
|
14
25
|
import com.google.android.gms.maps.model.LatLng
|
|
26
|
+
import com.google.android.gms.maps.model.LatLngBounds
|
|
15
27
|
import com.google.android.gms.maps.model.MapColorScheme
|
|
16
28
|
import com.google.android.gms.maps.model.Marker
|
|
17
29
|
import com.google.android.gms.maps.model.Polygon
|
|
18
30
|
import com.google.android.gms.maps.model.PolygonOptions
|
|
19
31
|
import com.google.android.gms.maps.model.PolylineOptions
|
|
32
|
+
import com.google.android.gms.maps.model.TileOverlayOptions
|
|
33
|
+
import com.google.android.gms.maps.model.UrlTileProvider
|
|
34
|
+
import com.luggmaps.LuggCalloutView
|
|
35
|
+
import com.luggmaps.LuggCircleView
|
|
36
|
+
import com.luggmaps.LuggCircleViewDelegate
|
|
37
|
+
import com.luggmaps.LuggGroundOverlayView
|
|
38
|
+
import com.luggmaps.LuggGroundOverlayViewDelegate
|
|
20
39
|
import com.luggmaps.LuggMapWrapperView
|
|
21
40
|
import com.luggmaps.LuggMarkerView
|
|
22
41
|
import com.luggmaps.LuggMarkerViewDelegate
|
|
@@ -24,6 +43,13 @@ import com.luggmaps.LuggPolygonView
|
|
|
24
43
|
import com.luggmaps.LuggPolygonViewDelegate
|
|
25
44
|
import com.luggmaps.LuggPolylineView
|
|
26
45
|
import com.luggmaps.LuggPolylineViewDelegate
|
|
46
|
+
import com.luggmaps.LuggTileOverlayView
|
|
47
|
+
import com.luggmaps.LuggTileOverlayViewDelegate
|
|
48
|
+
import com.luggmaps.extensions.findViewByTag
|
|
49
|
+
import java.net.URL
|
|
50
|
+
import kotlin.math.atan
|
|
51
|
+
import kotlin.math.pow
|
|
52
|
+
import kotlin.math.sinh
|
|
27
53
|
|
|
28
54
|
class GoogleMapProvider(private val context: Context) :
|
|
29
55
|
MapProvider,
|
|
@@ -31,14 +57,21 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
31
57
|
LuggMarkerViewDelegate,
|
|
32
58
|
LuggPolylineViewDelegate,
|
|
33
59
|
LuggPolygonViewDelegate,
|
|
60
|
+
LuggCircleViewDelegate,
|
|
61
|
+
LuggGroundOverlayViewDelegate,
|
|
62
|
+
LuggTileOverlayViewDelegate,
|
|
34
63
|
GoogleMap.OnCameraMoveStartedListener,
|
|
35
64
|
GoogleMap.OnCameraMoveListener,
|
|
36
65
|
GoogleMap.OnCameraIdleListener,
|
|
37
66
|
GoogleMap.OnMapClickListener,
|
|
38
67
|
GoogleMap.OnMapLongClickListener,
|
|
39
68
|
GoogleMap.OnPolygonClickListener,
|
|
69
|
+
GoogleMap.OnCircleClickListener,
|
|
70
|
+
GoogleMap.OnGroundOverlayClickListener,
|
|
40
71
|
GoogleMap.OnMarkerClickListener,
|
|
41
|
-
GoogleMap.OnMarkerDragListener
|
|
72
|
+
GoogleMap.OnMarkerDragListener,
|
|
73
|
+
GoogleMap.InfoWindowAdapter,
|
|
74
|
+
ComponentCallbacks2 {
|
|
42
75
|
|
|
43
76
|
override var delegate: MapProviderDelegate? = null
|
|
44
77
|
override val isMapReady: Boolean get() = _isMapReady
|
|
@@ -46,6 +79,7 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
46
79
|
var mapId: String = DEMO_MAP_ID
|
|
47
80
|
|
|
48
81
|
private var wrapperView: LuggMapWrapperView? = null
|
|
82
|
+
private var currentNightMode: Int = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
|
|
49
83
|
private var mapView: MapView? = null
|
|
50
84
|
private var googleMap: GoogleMap? = null
|
|
51
85
|
private var _isMapReady = false
|
|
@@ -53,9 +87,16 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
53
87
|
private val pendingMarkerViews = mutableSetOf<LuggMarkerView>()
|
|
54
88
|
private val pendingPolylineViews = mutableSetOf<LuggPolylineView>()
|
|
55
89
|
private val pendingPolygonViews = mutableSetOf<LuggPolygonView>()
|
|
90
|
+
private val pendingCircleViews = mutableSetOf<LuggCircleView>()
|
|
91
|
+
private val pendingGroundOverlayViews = mutableSetOf<LuggGroundOverlayView>()
|
|
92
|
+
private val pendingTileOverlayViews = mutableSetOf<LuggTileOverlayView>()
|
|
56
93
|
private val polylineAnimators = mutableMapOf<LuggPolylineView, PolylineAnimator>()
|
|
57
94
|
private val polygonToViewMap = mutableMapOf<Polygon, LuggPolygonView>()
|
|
95
|
+
private val circleToViewMap = mutableMapOf<Circle, LuggCircleView>()
|
|
96
|
+
private val groundOverlayToViewMap = mutableMapOf<GroundOverlay, LuggGroundOverlayView>()
|
|
58
97
|
private val markerToViewMap = mutableMapOf<Marker, LuggMarkerView>()
|
|
98
|
+
private val liveMarkerViews = mutableSetOf<LuggMarkerView>()
|
|
99
|
+
private var activeNonBubbledMarker: Marker? = null
|
|
59
100
|
private var tapLocation: LatLng? = null
|
|
60
101
|
|
|
61
102
|
// Initial camera settings
|
|
@@ -81,6 +122,10 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
81
122
|
// Edge Insets
|
|
82
123
|
private var edgeInsets: EdgeInsets = EdgeInsets()
|
|
83
124
|
|
|
125
|
+
// Inset adjustment
|
|
126
|
+
private var insetAdjustment: String = "never"
|
|
127
|
+
private var systemInsets: EdgeInsets = EdgeInsets()
|
|
128
|
+
|
|
84
129
|
// region MapProvider
|
|
85
130
|
|
|
86
131
|
override fun initializeMap(wrapperView: View, latitude: Double, longitude: Double, zoom: Float) {
|
|
@@ -93,6 +138,8 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
93
138
|
val wrapper = wrapperView as LuggMapWrapperView
|
|
94
139
|
this.wrapperView = wrapper
|
|
95
140
|
|
|
141
|
+
context.applicationContext.registerComponentCallbacks(this)
|
|
142
|
+
|
|
96
143
|
val options = GoogleMapOptions().mapId(mapId)
|
|
97
144
|
mapView = MapView(context, options).also { view ->
|
|
98
145
|
view.onCreate(null)
|
|
@@ -103,12 +150,24 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
103
150
|
}
|
|
104
151
|
|
|
105
152
|
override fun destroy() {
|
|
153
|
+
detachWindowInsetsListener()
|
|
154
|
+
context.applicationContext.unregisterComponentCallbacks(this)
|
|
155
|
+
dismissNonBubbledCallout()
|
|
156
|
+
for (markerView in liveMarkerViews) {
|
|
157
|
+
markerView.onUpdate = null
|
|
158
|
+
}
|
|
159
|
+
liveMarkerViews.clear()
|
|
106
160
|
pendingMarkerViews.clear()
|
|
107
161
|
pendingPolylineViews.clear()
|
|
108
162
|
pendingPolygonViews.clear()
|
|
163
|
+
pendingCircleViews.clear()
|
|
164
|
+
pendingGroundOverlayViews.clear()
|
|
165
|
+
pendingTileOverlayViews.clear()
|
|
109
166
|
polylineAnimators.values.forEach { it.destroy() }
|
|
110
167
|
polylineAnimators.clear()
|
|
111
168
|
polygonToViewMap.clear()
|
|
169
|
+
circleToViewMap.clear()
|
|
170
|
+
groundOverlayToViewMap.clear()
|
|
112
171
|
markerToViewMap.clear()
|
|
113
172
|
wrapperView?.touchEventHandler = null
|
|
114
173
|
wrapperView = null
|
|
@@ -118,8 +177,11 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
118
177
|
googleMap?.setOnMapClickListener(null)
|
|
119
178
|
googleMap?.setOnMapLongClickListener(null)
|
|
120
179
|
googleMap?.setOnPolygonClickListener(null)
|
|
180
|
+
googleMap?.setOnCircleClickListener(null)
|
|
181
|
+
googleMap?.setOnGroundOverlayClickListener(null)
|
|
121
182
|
googleMap?.setOnMarkerClickListener(null)
|
|
122
183
|
googleMap?.setOnMarkerDragListener(null)
|
|
184
|
+
googleMap?.setInfoWindowAdapter(null)
|
|
123
185
|
googleMap?.clear()
|
|
124
186
|
googleMap = null
|
|
125
187
|
_isMapReady = false
|
|
@@ -141,8 +203,11 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
141
203
|
map.setOnMapClickListener(this)
|
|
142
204
|
map.setOnMapLongClickListener(this)
|
|
143
205
|
map.setOnPolygonClickListener(this)
|
|
206
|
+
map.setOnCircleClickListener(this)
|
|
207
|
+
map.setOnGroundOverlayClickListener(this)
|
|
144
208
|
map.setOnMarkerClickListener(this)
|
|
145
209
|
map.setOnMarkerDragListener(this)
|
|
210
|
+
map.setInfoWindowAdapter(this)
|
|
146
211
|
|
|
147
212
|
wrapperView?.touchEventHandler = { event ->
|
|
148
213
|
if (event.action == android.view.MotionEvent.ACTION_DOWN) {
|
|
@@ -153,11 +218,15 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
153
218
|
applyUiSettings()
|
|
154
219
|
applyZoomLimits()
|
|
155
220
|
applyEdgeInsets()
|
|
221
|
+
applyInsetAdjustment()
|
|
156
222
|
applyTheme()
|
|
157
223
|
applyUserLocation()
|
|
158
224
|
processPendingMarkers()
|
|
159
225
|
processPendingPolylines()
|
|
160
226
|
processPendingPolygons()
|
|
227
|
+
processPendingCircles()
|
|
228
|
+
processPendingGroundOverlays()
|
|
229
|
+
processPendingTileOverlays()
|
|
161
230
|
|
|
162
231
|
delegate?.mapProviderDidReady()
|
|
163
232
|
}
|
|
@@ -177,6 +246,8 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
177
246
|
val map = googleMap ?: return
|
|
178
247
|
val position = map.cameraPosition
|
|
179
248
|
delegate?.mapProviderDidMoveCamera(position.target.latitude, position.target.longitude, position.zoom, isDragging)
|
|
249
|
+
positionLiveMarkers()
|
|
250
|
+
positionNonBubbledCallout()
|
|
180
251
|
}
|
|
181
252
|
|
|
182
253
|
override fun onCameraIdle() {
|
|
@@ -190,6 +261,7 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
190
261
|
}
|
|
191
262
|
|
|
192
263
|
override fun onMapClick(latLng: LatLng) {
|
|
264
|
+
dismissNonBubbledCallout()
|
|
193
265
|
val map = googleMap ?: return
|
|
194
266
|
val point = map.projection.toScreenLocation(latLng)
|
|
195
267
|
delegate?.mapProviderDidPress(latLng.latitude, latLng.longitude, point.x.toFloat(), point.y.toFloat())
|
|
@@ -210,10 +282,42 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
210
282
|
}
|
|
211
283
|
}
|
|
212
284
|
|
|
285
|
+
override fun onCircleClick(circle: Circle) {
|
|
286
|
+
val circleView = circleToViewMap[circle]
|
|
287
|
+
if (circleView?.tappable == true) {
|
|
288
|
+
circleView.emitPressEvent()
|
|
289
|
+
} else {
|
|
290
|
+
onMapClick(tapLocation ?: return)
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
override fun onGroundOverlayClick(groundOverlay: GroundOverlay) {
|
|
295
|
+
val view = groundOverlayToViewMap[groundOverlay]
|
|
296
|
+
if (view?.tappable == true) {
|
|
297
|
+
view.emitPressEvent()
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
213
301
|
override fun onMarkerClick(marker: Marker): Boolean {
|
|
302
|
+
dismissNonBubbledCallout()
|
|
303
|
+
|
|
214
304
|
markerToViewMap[marker]?.let { view ->
|
|
215
305
|
val point = googleMap?.projection?.toScreenLocation(marker.position)
|
|
216
306
|
view.emitPressEvent(point?.x?.toFloat() ?: 0f, point?.y?.toFloat() ?: 0f)
|
|
307
|
+
|
|
308
|
+
val calloutView = view.calloutView
|
|
309
|
+
if (calloutView != null && !calloutView.bubbled && calloutView.hasCustomContent) {
|
|
310
|
+
if (view.centerOnPress) {
|
|
311
|
+
googleMap?.animateCamera(CameraUpdateFactory.newLatLng(marker.position))
|
|
312
|
+
}
|
|
313
|
+
showNonBubbledCallout(marker, calloutView)
|
|
314
|
+
return true
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (!view.centerOnPress) {
|
|
318
|
+
marker.showInfoWindow()
|
|
319
|
+
return true
|
|
320
|
+
}
|
|
217
321
|
}
|
|
218
322
|
return false
|
|
219
323
|
}
|
|
@@ -224,6 +328,7 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
224
328
|
view.setCoordinate(marker.position.latitude, marker.position.longitude)
|
|
225
329
|
val point = googleMap?.projection?.toScreenLocation(marker.position)
|
|
226
330
|
view.emitDragStartEvent(point?.x?.toFloat() ?: 0f, point?.y?.toFloat() ?: 0f)
|
|
331
|
+
if (!view.rasterize) positionLiveMarker(view)
|
|
227
332
|
}
|
|
228
333
|
}
|
|
229
334
|
|
|
@@ -232,6 +337,7 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
232
337
|
view.setCoordinate(marker.position.latitude, marker.position.longitude)
|
|
233
338
|
val point = googleMap?.projection?.toScreenLocation(marker.position)
|
|
234
339
|
view.emitDragChangeEvent(point?.x?.toFloat() ?: 0f, point?.y?.toFloat() ?: 0f)
|
|
340
|
+
if (!view.rasterize) positionLiveMarker(view)
|
|
235
341
|
}
|
|
236
342
|
}
|
|
237
343
|
|
|
@@ -241,7 +347,92 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
241
347
|
view.setCoordinate(marker.position.latitude, marker.position.longitude)
|
|
242
348
|
val point = googleMap?.projection?.toScreenLocation(marker.position)
|
|
243
349
|
view.emitDragEndEvent(point?.x?.toFloat() ?: 0f, point?.y?.toFloat() ?: 0f)
|
|
350
|
+
if (!view.rasterize) positionLiveMarker(view)
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
override fun getInfoWindow(marker: Marker): View? {
|
|
355
|
+
// Non-bubbled callouts are rendered as live views, not info windows
|
|
356
|
+
return null
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
override fun getInfoContents(marker: Marker): View? {
|
|
360
|
+
val markerView = markerToViewMap[marker] ?: return null
|
|
361
|
+
val calloutView = markerView.calloutView ?: return null
|
|
362
|
+
if (!calloutView.hasCustomContent || !calloutView.bubbled) return null
|
|
363
|
+
|
|
364
|
+
val bitmap = calloutView.createContentBitmap() ?: return null
|
|
365
|
+
return ImageView(context).apply { setImageBitmap(bitmap) }
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
private fun showNonBubbledCallout(marker: Marker, calloutView: LuggCalloutView) {
|
|
369
|
+
val wrapper = wrapperView ?: return
|
|
370
|
+
val contentView = calloutView.contentView
|
|
371
|
+
|
|
372
|
+
calloutView.onUpdate = {
|
|
373
|
+
layoutNonBubbledCallout()
|
|
374
|
+
positionNonBubbledCallout()
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
dismissInfoWindows()
|
|
378
|
+
wrapper.addView(contentView)
|
|
379
|
+
activeNonBubbledMarker = marker
|
|
380
|
+
layoutNonBubbledCallout()
|
|
381
|
+
positionNonBubbledCallout()
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
private fun dismissInfoWindows() {
|
|
385
|
+
for ((marker, _) in markerToViewMap) {
|
|
386
|
+
if (marker.isInfoWindowShown) {
|
|
387
|
+
marker.hideInfoWindow()
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
private fun dismissNonBubbledCallout() {
|
|
393
|
+
val marker = activeNonBubbledMarker ?: return
|
|
394
|
+
val markerView = markerToViewMap[marker] ?: return
|
|
395
|
+
val calloutView = markerView.calloutView ?: return
|
|
396
|
+
val contentView = calloutView.contentView
|
|
397
|
+
|
|
398
|
+
calloutView.onUpdate = null
|
|
399
|
+
(contentView.parent as? android.view.ViewGroup)?.removeView(contentView)
|
|
400
|
+
activeNonBubbledMarker = null
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
private fun layoutNonBubbledCallout() {
|
|
404
|
+
val marker = activeNonBubbledMarker ?: return
|
|
405
|
+
val markerView = markerToViewMap[marker] ?: return
|
|
406
|
+
val calloutView = markerView.calloutView ?: return
|
|
407
|
+
val contentView = calloutView.contentView
|
|
408
|
+
|
|
409
|
+
var contentWidth = 0
|
|
410
|
+
var contentHeight = 0
|
|
411
|
+
for (i in 0 until contentView.childCount) {
|
|
412
|
+
val child = contentView.getChildAt(i)
|
|
413
|
+
val childRight = child.left + child.width
|
|
414
|
+
val childBottom = child.top + child.height
|
|
415
|
+
if (childRight > contentWidth) contentWidth = childRight
|
|
416
|
+
if (childBottom > contentHeight) contentHeight = childBottom
|
|
244
417
|
}
|
|
418
|
+
|
|
419
|
+
contentView.measure(
|
|
420
|
+
View.MeasureSpec.makeMeasureSpec(contentWidth, View.MeasureSpec.EXACTLY),
|
|
421
|
+
View.MeasureSpec.makeMeasureSpec(contentHeight, View.MeasureSpec.EXACTLY)
|
|
422
|
+
)
|
|
423
|
+
contentView.layout(0, 0, contentWidth, contentHeight)
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
private fun positionNonBubbledCallout() {
|
|
427
|
+
val marker = activeNonBubbledMarker ?: return
|
|
428
|
+
val markerView = markerToViewMap[marker] ?: return
|
|
429
|
+
val calloutView = markerView.calloutView ?: return
|
|
430
|
+
val contentView = calloutView.contentView
|
|
431
|
+
val map = googleMap ?: return
|
|
432
|
+
|
|
433
|
+
val point = map.projection.toScreenLocation(marker.position)
|
|
434
|
+
contentView.translationX = point.x - contentView.width / 2f + calloutView.offsetX
|
|
435
|
+
contentView.translationY = point.y - markerView.scaledContentHeight * markerView.anchorY - contentView.height + calloutView.offsetY
|
|
245
436
|
}
|
|
246
437
|
|
|
247
438
|
// endregion
|
|
@@ -285,6 +476,15 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
285
476
|
googleMap?.uiSettings?.isMyLocationButtonEnabled = enabled
|
|
286
477
|
}
|
|
287
478
|
|
|
479
|
+
override fun setMapType(value: String) {
|
|
480
|
+
googleMap?.mapType = when (value) {
|
|
481
|
+
"satellite" -> GoogleMap.MAP_TYPE_SATELLITE
|
|
482
|
+
"terrain" -> GoogleMap.MAP_TYPE_TERRAIN
|
|
483
|
+
"hybrid" -> GoogleMap.MAP_TYPE_HYBRID
|
|
484
|
+
else -> GoogleMap.MAP_TYPE_NORMAL
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
288
488
|
override fun setTheme(value: String) {
|
|
289
489
|
theme = value
|
|
290
490
|
applyTheme()
|
|
@@ -324,7 +524,7 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
324
524
|
|
|
325
525
|
if (map != null && oldInsets != edgeInsets) {
|
|
326
526
|
val cameraUpdate = CameraUpdateFactory.newCameraPosition(map.cameraPosition)
|
|
327
|
-
applyEdgeInsets()
|
|
527
|
+
applyEdgeInsets(duration)
|
|
328
528
|
when {
|
|
329
529
|
duration < 0 -> map.animateCamera(cameraUpdate)
|
|
330
530
|
duration > 0 -> map.animateCamera(cameraUpdate, duration, null)
|
|
@@ -335,6 +535,17 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
335
535
|
}
|
|
336
536
|
}
|
|
337
537
|
|
|
538
|
+
override fun setInsetAdjustment(value: String) {
|
|
539
|
+
insetAdjustment = value
|
|
540
|
+
applyInsetAdjustment()
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
override fun setPoiEnabled(enabled: Boolean) {}
|
|
544
|
+
|
|
545
|
+
override fun setPoiFilterMode(mode: String) {}
|
|
546
|
+
|
|
547
|
+
override fun setPoiFilterCategories(categories: List<String>) {}
|
|
548
|
+
|
|
338
549
|
// endregion
|
|
339
550
|
|
|
340
551
|
// region MarkerViewDelegate
|
|
@@ -356,6 +567,30 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
356
567
|
syncMarkerView(markerView)
|
|
357
568
|
}
|
|
358
569
|
|
|
570
|
+
override fun showCalloutForMarkerView(markerView: LuggMarkerView) {
|
|
571
|
+
val marker = markerView.marker ?: return
|
|
572
|
+
val calloutView = markerView.calloutView
|
|
573
|
+
|
|
574
|
+
if (calloutView != null && calloutView.hasCustomContent) {
|
|
575
|
+
dismissNonBubbledCallout()
|
|
576
|
+
if (calloutView.bubbled) {
|
|
577
|
+
marker.showInfoWindow()
|
|
578
|
+
} else {
|
|
579
|
+
showNonBubbledCallout(marker, calloutView)
|
|
580
|
+
}
|
|
581
|
+
return
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
if (!markerView.title.isNullOrEmpty()) {
|
|
585
|
+
marker.showInfoWindow()
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
override fun hideCalloutForMarkerView(markerView: LuggMarkerView) {
|
|
590
|
+
dismissNonBubbledCallout()
|
|
591
|
+
markerView.marker?.hideInfoWindow()
|
|
592
|
+
}
|
|
593
|
+
|
|
359
594
|
// endregion
|
|
360
595
|
|
|
361
596
|
// region PolylineViewDelegate
|
|
@@ -374,6 +609,30 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
374
609
|
|
|
375
610
|
// endregion
|
|
376
611
|
|
|
612
|
+
// region CircleViewDelegate
|
|
613
|
+
|
|
614
|
+
override fun circleViewDidUpdate(circleView: LuggCircleView) {
|
|
615
|
+
syncCircleView(circleView)
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// endregion
|
|
619
|
+
|
|
620
|
+
// region GroundOverlayViewDelegate
|
|
621
|
+
|
|
622
|
+
override fun groundOverlayViewDidUpdate(groundOverlayView: LuggGroundOverlayView) {
|
|
623
|
+
syncGroundOverlayView(groundOverlayView)
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// endregion
|
|
627
|
+
|
|
628
|
+
// region TileOverlayViewDelegate
|
|
629
|
+
|
|
630
|
+
override fun tileOverlayViewDidUpdate(tileOverlayView: LuggTileOverlayView) {
|
|
631
|
+
syncTileOverlayView(tileOverlayView)
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// endregion
|
|
635
|
+
|
|
377
636
|
// region Marker Management
|
|
378
637
|
|
|
379
638
|
override fun addMarkerView(markerView: LuggMarkerView) {
|
|
@@ -382,6 +641,7 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
382
641
|
}
|
|
383
642
|
|
|
384
643
|
override fun removeMarkerView(markerView: LuggMarkerView) {
|
|
644
|
+
removeLiveMarker(markerView)
|
|
385
645
|
markerView.marker?.let { markerToViewMap.remove(it) }
|
|
386
646
|
markerView.marker?.remove()
|
|
387
647
|
markerView.marker = null
|
|
@@ -411,9 +671,14 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
411
671
|
isDraggable = markerView.draggable
|
|
412
672
|
}
|
|
413
673
|
|
|
414
|
-
if (markerView.hasCustomView
|
|
415
|
-
markerView.
|
|
416
|
-
|
|
674
|
+
if (markerView.hasCustomView) {
|
|
675
|
+
if (markerView.scaleChanged) {
|
|
676
|
+
markerView.applyScaleToMarker()
|
|
677
|
+
markerView.clearScaleChanged()
|
|
678
|
+
}
|
|
679
|
+
if (!markerView.rasterize) {
|
|
680
|
+
positionLiveMarker(markerView)
|
|
681
|
+
}
|
|
417
682
|
}
|
|
418
683
|
}
|
|
419
684
|
|
|
@@ -440,7 +705,64 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
440
705
|
|
|
441
706
|
markerView.marker = marker
|
|
442
707
|
markerToViewMap[marker] = markerView
|
|
443
|
-
|
|
708
|
+
|
|
709
|
+
if (markerView.hasCustomView) {
|
|
710
|
+
if (markerView.rasterize) {
|
|
711
|
+
markerView.applyIconToMarker()
|
|
712
|
+
} else {
|
|
713
|
+
showLiveMarker(markerView)
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Workaround: AdvancedMarker.iconView is buggy on Android, so we manually add the custom
|
|
719
|
+
// content view to the wrapper and position it via screen projection instead. The underlying
|
|
720
|
+
// marker uses a transparent bitmap matching the content size so taps still trigger onMarkerClick.
|
|
721
|
+
private fun showLiveMarker(markerView: LuggMarkerView) {
|
|
722
|
+
val wrapper = wrapperView ?: return
|
|
723
|
+
|
|
724
|
+
markerView.onUpdate = {
|
|
725
|
+
updateLiveMarkerHitArea(markerView)
|
|
726
|
+
positionLiveMarker(markerView)
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
val contentView = markerView.contentView
|
|
730
|
+
contentView.pointerEvents = com.facebook.react.uimanager.PointerEvents.NONE
|
|
731
|
+
(contentView.parent as? android.view.ViewGroup)?.removeView(contentView)
|
|
732
|
+
wrapper.addView(contentView)
|
|
733
|
+
liveMarkerViews.add(markerView)
|
|
734
|
+
markerView.layoutContentView()
|
|
735
|
+
updateLiveMarkerHitArea(markerView)
|
|
736
|
+
positionLiveMarker(markerView)
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
private fun updateLiveMarkerHitArea(markerView: LuggMarkerView) {
|
|
740
|
+
val marker = markerView.marker ?: return
|
|
741
|
+
val contentView = markerView.contentView
|
|
742
|
+
val w = contentView.width.coerceAtLeast(1)
|
|
743
|
+
val h = contentView.height.coerceAtLeast(1)
|
|
744
|
+
marker.setIcon(BitmapDescriptorFactory.fromBitmap(createBitmap(w, h)))
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
private fun removeLiveMarker(markerView: LuggMarkerView) {
|
|
748
|
+
markerView.onUpdate = null
|
|
749
|
+
val contentView = markerView.contentView
|
|
750
|
+
(contentView.parent as? android.view.ViewGroup)?.removeView(contentView)
|
|
751
|
+
liveMarkerViews.remove(markerView)
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
private fun positionLiveMarkers() {
|
|
755
|
+
for (markerView in liveMarkerViews) {
|
|
756
|
+
positionLiveMarker(markerView)
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
private fun positionLiveMarker(markerView: LuggMarkerView) {
|
|
761
|
+
val map = googleMap ?: return
|
|
762
|
+
val contentView = markerView.contentView
|
|
763
|
+
val point = map.projection.toScreenLocation(LatLng(markerView.latitude, markerView.longitude))
|
|
764
|
+
contentView.translationX = point.x - contentView.width * markerView.anchorX
|
|
765
|
+
contentView.translationY = point.y - contentView.height * markerView.anchorY
|
|
444
766
|
}
|
|
445
767
|
|
|
446
768
|
// endregion
|
|
@@ -577,6 +899,218 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
577
899
|
|
|
578
900
|
// endregion
|
|
579
901
|
|
|
902
|
+
// region Circle Management
|
|
903
|
+
|
|
904
|
+
override fun addCircleView(circleView: LuggCircleView) {
|
|
905
|
+
circleView.delegate = this
|
|
906
|
+
syncCircleView(circleView)
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
override fun removeCircleView(circleView: LuggCircleView) {
|
|
910
|
+
circleView.circle?.let { circleToViewMap.remove(it) }
|
|
911
|
+
circleView.circle?.remove()
|
|
912
|
+
circleView.circle = null
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
private fun syncCircleView(circleView: LuggCircleView) {
|
|
916
|
+
if (googleMap == null) {
|
|
917
|
+
pendingCircleViews.add(circleView)
|
|
918
|
+
return
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
if (circleView.circle == null) {
|
|
922
|
+
addCircleViewToMap(circleView)
|
|
923
|
+
return
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
circleView.circle?.apply {
|
|
927
|
+
center = circleView.center
|
|
928
|
+
radius = circleView.radius
|
|
929
|
+
fillColor = circleView.fillColor
|
|
930
|
+
strokeColor = circleView.strokeColor
|
|
931
|
+
strokeWidth = circleView.strokeWidth.dpToPx()
|
|
932
|
+
zIndex = circleView.zIndex
|
|
933
|
+
isClickable = true
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
private fun processPendingCircles() {
|
|
938
|
+
if (googleMap == null) return
|
|
939
|
+
pendingCircleViews.forEach { addCircleViewToMap(it) }
|
|
940
|
+
pendingCircleViews.clear()
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
private fun addCircleViewToMap(circleView: LuggCircleView) {
|
|
944
|
+
val map = googleMap ?: return
|
|
945
|
+
|
|
946
|
+
val options = CircleOptions()
|
|
947
|
+
.center(circleView.center)
|
|
948
|
+
.radius(circleView.radius)
|
|
949
|
+
.fillColor(circleView.fillColor)
|
|
950
|
+
.strokeColor(circleView.strokeColor)
|
|
951
|
+
.strokeWidth(circleView.strokeWidth.dpToPx())
|
|
952
|
+
.zIndex(circleView.zIndex)
|
|
953
|
+
.clickable(true)
|
|
954
|
+
|
|
955
|
+
val circle = map.addCircle(options)
|
|
956
|
+
circleView.circle = circle
|
|
957
|
+
circleToViewMap[circle] = circleView
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// endregion
|
|
961
|
+
|
|
962
|
+
// region Ground Overlay Management
|
|
963
|
+
|
|
964
|
+
override fun addGroundOverlayView(groundOverlayView: LuggGroundOverlayView) {
|
|
965
|
+
groundOverlayView.delegate = this
|
|
966
|
+
syncGroundOverlayView(groundOverlayView)
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
override fun removeGroundOverlayView(groundOverlayView: LuggGroundOverlayView) {
|
|
970
|
+
groundOverlayView.delegate = null
|
|
971
|
+
groundOverlayView.groundOverlay?.let { groundOverlayToViewMap.remove(it) }
|
|
972
|
+
groundOverlayView.groundOverlay?.remove()
|
|
973
|
+
groundOverlayView.groundOverlay = null
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
private fun syncGroundOverlayView(groundOverlayView: LuggGroundOverlayView) {
|
|
977
|
+
if (googleMap == null) {
|
|
978
|
+
pendingGroundOverlayViews.add(groundOverlayView)
|
|
979
|
+
return
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
val imageUri = groundOverlayView.imageUri
|
|
983
|
+
if (imageUri.isEmpty()) return
|
|
984
|
+
|
|
985
|
+
// Remove old overlay
|
|
986
|
+
groundOverlayView.groundOverlay?.let { groundOverlayToViewMap.remove(it) }
|
|
987
|
+
groundOverlayView.groundOverlay?.remove()
|
|
988
|
+
groundOverlayView.groundOverlay = null
|
|
989
|
+
|
|
990
|
+
// Load image async and add overlay
|
|
991
|
+
Thread {
|
|
992
|
+
try {
|
|
993
|
+
val connection = URL(imageUri).openConnection() as java.net.HttpURLConnection
|
|
994
|
+
connection.instanceFollowRedirects = true
|
|
995
|
+
connection.connect()
|
|
996
|
+
val bitmap = android.graphics.BitmapFactory.decodeStream(connection.inputStream)
|
|
997
|
+
connection.disconnect()
|
|
998
|
+
if (bitmap != null) {
|
|
999
|
+
mapView?.post {
|
|
1000
|
+
addGroundOverlayToMap(groundOverlayView, bitmap)
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
} catch (_: Exception) {}
|
|
1004
|
+
}.start()
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
private fun addGroundOverlayToMap(groundOverlayView: LuggGroundOverlayView, bitmap: android.graphics.Bitmap) {
|
|
1008
|
+
val map = googleMap ?: return
|
|
1009
|
+
|
|
1010
|
+
val bounds = LatLngBounds(groundOverlayView.southwest, groundOverlayView.northeast)
|
|
1011
|
+
val options = GroundOverlayOptions()
|
|
1012
|
+
.image(BitmapDescriptorFactory.fromBitmap(bitmap))
|
|
1013
|
+
.positionFromBounds(bounds)
|
|
1014
|
+
.transparency(1f - groundOverlayView.overlayOpacity)
|
|
1015
|
+
.bearing(groundOverlayView.bearing)
|
|
1016
|
+
.zIndex(groundOverlayView.zIndex)
|
|
1017
|
+
.clickable(groundOverlayView.tappable)
|
|
1018
|
+
|
|
1019
|
+
val overlay = map.addGroundOverlay(options)
|
|
1020
|
+
if (overlay != null) {
|
|
1021
|
+
groundOverlayView.groundOverlay = overlay
|
|
1022
|
+
groundOverlayToViewMap[overlay] = groundOverlayView
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
private fun processPendingGroundOverlays() {
|
|
1027
|
+
if (googleMap == null) return
|
|
1028
|
+
pendingGroundOverlayViews.forEach { syncGroundOverlayView(it) }
|
|
1029
|
+
pendingGroundOverlayViews.clear()
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
// endregion
|
|
1033
|
+
|
|
1034
|
+
// region Tile Overlay Management
|
|
1035
|
+
|
|
1036
|
+
override fun addTileOverlayView(tileOverlayView: LuggTileOverlayView) {
|
|
1037
|
+
tileOverlayView.delegate = this
|
|
1038
|
+
syncTileOverlayView(tileOverlayView)
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
override fun removeTileOverlayView(tileOverlayView: LuggTileOverlayView) {
|
|
1042
|
+
tileOverlayView.delegate = null
|
|
1043
|
+
tileOverlayView.tileOverlay?.remove()
|
|
1044
|
+
tileOverlayView.tileOverlay = null
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
private fun syncTileOverlayView(tileOverlayView: LuggTileOverlayView) {
|
|
1048
|
+
if (googleMap == null) {
|
|
1049
|
+
pendingTileOverlayViews.add(tileOverlayView)
|
|
1050
|
+
return
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
val urlTemplate = tileOverlayView.urlTemplate
|
|
1054
|
+
if (urlTemplate.isEmpty()) return
|
|
1055
|
+
|
|
1056
|
+
// Remove old overlay
|
|
1057
|
+
tileOverlayView.tileOverlay?.remove()
|
|
1058
|
+
tileOverlayView.tileOverlay = null
|
|
1059
|
+
|
|
1060
|
+
val tileSize = tileOverlayView.tileSize
|
|
1061
|
+
val hasBounds = tileOverlayView.hasBounds
|
|
1062
|
+
val swLat = tileOverlayView.boundsSwLat
|
|
1063
|
+
val swLng = tileOverlayView.boundsSwLng
|
|
1064
|
+
val neLat = tileOverlayView.boundsNeLat
|
|
1065
|
+
val neLng = tileOverlayView.boundsNeLng
|
|
1066
|
+
|
|
1067
|
+
val tileProvider = object : UrlTileProvider(tileSize, tileSize) {
|
|
1068
|
+
override fun getTileUrl(x: Int, y: Int, zoom: Int): URL? {
|
|
1069
|
+
if (hasBounds) {
|
|
1070
|
+
val n = 2.0.pow(zoom.toDouble())
|
|
1071
|
+
val tileSWLat = Math.toDegrees(atan(sinh(Math.PI * (1 - 2.0 * (y + 1) / n))))
|
|
1072
|
+
val tileNELat = Math.toDegrees(atan(sinh(Math.PI * (1 - 2.0 * y / n))))
|
|
1073
|
+
val tileSWLng = x / n * 360.0 - 180.0
|
|
1074
|
+
val tileNELng = (x + 1) / n * 360.0 - 180.0
|
|
1075
|
+
|
|
1076
|
+
if (tileNELat < swLat ||
|
|
1077
|
+
tileSWLat > neLat ||
|
|
1078
|
+
tileNELng < swLng ||
|
|
1079
|
+
tileSWLng > neLng
|
|
1080
|
+
) {
|
|
1081
|
+
return null
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
val url = urlTemplate
|
|
1086
|
+
.replace("{x}", x.toString())
|
|
1087
|
+
.replace("{y}", y.toString())
|
|
1088
|
+
.replace("{z}", zoom.toString())
|
|
1089
|
+
return try {
|
|
1090
|
+
URL(url)
|
|
1091
|
+
} catch (_: Exception) {
|
|
1092
|
+
null
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
val options = TileOverlayOptions()
|
|
1098
|
+
.tileProvider(tileProvider)
|
|
1099
|
+
.transparency(1f - tileOverlayView.overlayOpacity)
|
|
1100
|
+
.zIndex(tileOverlayView.zIndex)
|
|
1101
|
+
|
|
1102
|
+
val overlay = googleMap?.addTileOverlay(options)
|
|
1103
|
+
tileOverlayView.tileOverlay = overlay
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
private fun processPendingTileOverlays() {
|
|
1107
|
+
if (googleMap == null) return
|
|
1108
|
+
pendingTileOverlayViews.forEach { syncTileOverlayView(it) }
|
|
1109
|
+
pendingTileOverlayViews.clear()
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
// endregion
|
|
1113
|
+
|
|
580
1114
|
// region Lifecycle
|
|
581
1115
|
|
|
582
1116
|
override fun pauseAnimations() {
|
|
@@ -614,11 +1148,11 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
614
1148
|
val map = googleMap ?: return
|
|
615
1149
|
if (coordinates.isEmpty()) return
|
|
616
1150
|
|
|
617
|
-
val
|
|
618
|
-
if (
|
|
1151
|
+
val latLongs = coordinates.filterIsInstance<LatLng>()
|
|
1152
|
+
if (latLongs.isEmpty()) return
|
|
619
1153
|
|
|
620
|
-
val boundsBuilder =
|
|
621
|
-
|
|
1154
|
+
val boundsBuilder = LatLngBounds.Builder()
|
|
1155
|
+
latLongs.forEach { boundsBuilder.include(it) }
|
|
622
1156
|
val bounds = boundsBuilder.build()
|
|
623
1157
|
|
|
624
1158
|
val top = edgeInsetsTop.toFloat().dpToPx().toInt()
|
|
@@ -626,11 +1160,12 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
626
1160
|
val bottom = edgeInsetsBottom.toFloat().dpToPx().toInt()
|
|
627
1161
|
val right = edgeInsetsRight.toFloat().dpToPx().toInt()
|
|
628
1162
|
|
|
1163
|
+
val combined = combinedEdgeInsets()
|
|
629
1164
|
map.setPadding(
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
1165
|
+
combined.left + left,
|
|
1166
|
+
combined.top + top,
|
|
1167
|
+
combined.right + right,
|
|
1168
|
+
combined.bottom + bottom
|
|
634
1169
|
)
|
|
635
1170
|
|
|
636
1171
|
val cameraUpdate = CameraUpdateFactory.newLatLngBounds(bounds, 0)
|
|
@@ -641,7 +1176,7 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
641
1176
|
else -> map.moveCamera(cameraUpdate)
|
|
642
1177
|
}
|
|
643
1178
|
|
|
644
|
-
map.setPadding(
|
|
1179
|
+
map.setPadding(combined.left, combined.top, combined.right, combined.bottom)
|
|
645
1180
|
}
|
|
646
1181
|
|
|
647
1182
|
// endregion
|
|
@@ -665,17 +1200,92 @@ class GoogleMapProvider(private val context: Context) :
|
|
|
665
1200
|
}
|
|
666
1201
|
}
|
|
667
1202
|
|
|
668
|
-
private fun
|
|
669
|
-
|
|
1203
|
+
private fun applyInsetAdjustment() {
|
|
1204
|
+
if (insetAdjustment == "automatic") {
|
|
1205
|
+
attachWindowInsetsListener()
|
|
1206
|
+
} else {
|
|
1207
|
+
detachWindowInsetsListener()
|
|
1208
|
+
systemInsets = EdgeInsets()
|
|
1209
|
+
}
|
|
1210
|
+
applyEdgeInsets()
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
private fun combinedEdgeInsets(): EdgeInsets =
|
|
1214
|
+
if (insetAdjustment == "automatic") {
|
|
1215
|
+
EdgeInsets(
|
|
1216
|
+
edgeInsets.top + systemInsets.top,
|
|
1217
|
+
edgeInsets.left + systemInsets.left,
|
|
1218
|
+
edgeInsets.bottom + systemInsets.bottom,
|
|
1219
|
+
edgeInsets.right + systemInsets.right
|
|
1220
|
+
)
|
|
1221
|
+
} else {
|
|
1222
|
+
edgeInsets
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
private fun applyEdgeInsets(duration: Int = 0) {
|
|
1226
|
+
val combined = combinedEdgeInsets()
|
|
1227
|
+
googleMap?.setPadding(combined.left, combined.top, combined.right, combined.bottom)
|
|
1228
|
+
applyWatermarkTranslation(combined, duration)
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
private fun applyWatermarkTranslation(insets: EdgeInsets, duration: Int = 0) {
|
|
1232
|
+
val view = mapView ?: return
|
|
1233
|
+
view.findViewByTag("GoogleWatermark")?.let { watermark ->
|
|
1234
|
+
val targetY = -insets.bottom.toFloat()
|
|
1235
|
+
val targetX = insets.left.toFloat()
|
|
1236
|
+
if (duration > 0) {
|
|
1237
|
+
watermark.animate()
|
|
1238
|
+
.translationY(targetY)
|
|
1239
|
+
.translationX(targetX)
|
|
1240
|
+
.setDuration(duration.toLong())
|
|
1241
|
+
.start()
|
|
1242
|
+
} else if (duration < 0) {
|
|
1243
|
+
watermark.animate()
|
|
1244
|
+
.translationY(targetY)
|
|
1245
|
+
.translationX(targetX)
|
|
1246
|
+
.start()
|
|
1247
|
+
} else {
|
|
1248
|
+
watermark.translationY = targetY
|
|
1249
|
+
watermark.translationX = targetX
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
670
1252
|
}
|
|
671
1253
|
|
|
1254
|
+
private fun attachWindowInsetsListener() {
|
|
1255
|
+
val view = mapView ?: return
|
|
1256
|
+
ViewCompat.setOnApplyWindowInsetsListener(view) { _, windowInsets ->
|
|
1257
|
+
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
|
1258
|
+
systemInsets = EdgeInsets(insets.top, insets.left, insets.bottom, insets.right)
|
|
1259
|
+
applyEdgeInsets()
|
|
1260
|
+
windowInsets
|
|
1261
|
+
}
|
|
1262
|
+
ViewCompat.requestApplyInsets(view)
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
private fun detachWindowInsetsListener() {
|
|
1266
|
+
mapView?.let { ViewCompat.setOnApplyWindowInsetsListener(it, null) }
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
override fun onConfigurationChanged(newConfig: Configuration) {
|
|
1270
|
+
val newNightMode = newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
|
|
1271
|
+
if (newNightMode != currentNightMode) {
|
|
1272
|
+
currentNightMode = newNightMode
|
|
1273
|
+
applyTheme()
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
@Deprecated("Deprecated in Java")
|
|
1278
|
+
override fun onLowMemory() {}
|
|
1279
|
+
|
|
1280
|
+
override fun onTrimMemory(level: Int) {}
|
|
1281
|
+
|
|
672
1282
|
private fun applyTheme() {
|
|
673
1283
|
val colorScheme = when (theme) {
|
|
674
1284
|
"dark" -> MapColorScheme.DARK
|
|
675
1285
|
"light" -> MapColorScheme.LIGHT
|
|
676
1286
|
else -> MapColorScheme.FOLLOW_SYSTEM
|
|
677
1287
|
}
|
|
678
|
-
googleMap?.
|
|
1288
|
+
googleMap?.mapColorScheme = colorScheme
|
|
679
1289
|
}
|
|
680
1290
|
|
|
681
1291
|
@SuppressLint("MissingPermission")
|