11package com.rngooglemapsplus
22
3- import android.annotation.SuppressLint
43import android.location.Location
4+ import android.widget.FrameLayout
55import com.facebook.react.bridge.LifecycleEventListener
66import com.facebook.react.bridge.UiThreadUtil
77import com.facebook.react.uimanager.PixelUtil.dpToPx
88import com.facebook.react.uimanager.ThemedReactContext
99import com.google.android.gms.common.ConnectionResult
1010import com.google.android.gms.maps.CameraUpdateFactory
1111import com.google.android.gms.maps.GoogleMap
12+ import com.google.android.gms.maps.GoogleMapOptions
1213import com.google.android.gms.maps.MapView
13- import com.google.android.gms.maps.OnMapReadyCallback
1414import com.google.android.gms.maps.model.CameraPosition
1515import com.google.android.gms.maps.model.LatLng
1616import com.google.android.gms.maps.model.LatLngBounds
@@ -28,25 +28,17 @@ class GoogleMapsViewImpl(
2828 val locationHandler : LocationHandler ,
2929 val playServiceHandler : PlayServicesHandler ,
3030 val markerOptions : com.rngooglemapsplus.MarkerOptions ,
31- ) : MapView (reactContext),
31+ ) : FrameLayout (reactContext),
3232 GoogleMap .OnCameraMoveStartedListener ,
3333 GoogleMap .OnCameraMoveListener ,
3434 GoogleMap .OnCameraIdleListener ,
3535 GoogleMap .OnMapClickListener ,
36- OnMapReadyCallback ,
3736 GoogleMap .OnMarkerClickListener ,
3837 LifecycleEventListener {
38+ private var initialized = false
39+ private var mapReady = false
3940 private var googleMap: GoogleMap ? = null
40-
41- private var pendingBuildingEnabled: Boolean? = null
42- private var pendingTrafficEnabled: Boolean? = null
43- private var pendingCustomMapStyle: MapStyleOptions ? = null
44- private var pendingInitialCamera: CameraPosition ? = null
45- private var pendingUserInterfaceStyle: Int? = null
46- private var pendingMinZoomLevel: Double? = null
47- private var pendingMaxZoomLevel: Double? = null
48- private var pendingMapPadding: RNMapPadding ? = null
49- private var pendingMapType: Int? = null
41+ private var mapView: MapView ? = null
5042 private val pendingPolygons = mutableListOf<Pair <String , PolygonOptions >>()
5143 private val pendingPolylines = mutableListOf<Pair <String , PolylineOptions >>()
5244 private val pendingMarkers = mutableListOf<Pair <String , MarkerOptions >>()
@@ -61,10 +53,15 @@ class GoogleMapsViewImpl(
6153
6254 init {
6355 reactContext.addLifecycleEventListener(this )
64- getMap()
6556 }
6657
67- private fun getMap () {
58+ fun initMapView (
59+ mapId : String? ,
60+ liteMode : Boolean? ,
61+ cameraPosition : CameraPosition ? ,
62+ ) {
63+ if (initialized) return
64+ initialized = true
6865 val result = playServiceHandler.playServicesAvailability()
6966
7067 when (result) {
@@ -93,8 +90,35 @@ class GoogleMapsViewImpl(
9390 onMapError?.invoke(RNMapErrorCode .UNKNOWN )
9491 }
9592
96- onCreate(null )
97- getMapAsync(this @GoogleMapsViewImpl)
93+ mapView =
94+ MapView (
95+ reactContext,
96+ GoogleMapOptions ().apply {
97+ mapId?.let { mapId(it) }
98+ liteMode?.let { liteMode(it) }
99+ cameraPosition?.let {
100+ camera(it)
101+ }
102+ },
103+ )
104+
105+ super .addView(mapView)
106+
107+ mapView?.onCreate(null )
108+ mapView?.getMapAsync { map ->
109+ googleMap = map
110+ googleMap?.setOnMapLoadedCallback {
111+ googleMap?.setOnCameraMoveStartedListener(this @GoogleMapsViewImpl)
112+ googleMap?.setOnCameraMoveListener(this @GoogleMapsViewImpl)
113+ googleMap?.setOnCameraIdleListener(this @GoogleMapsViewImpl)
114+ googleMap?.setOnMarkerClickListener(this @GoogleMapsViewImpl)
115+ googleMap?.setOnMapClickListener(this @GoogleMapsViewImpl)
116+ }
117+ initLocationCallbacks()
118+ applyPending()
119+ }
120+ mapReady = true
121+ onMapReady?.invoke(true )
98122 }
99123
100124 override fun onCameraMoveStarted (reason : Int ) {
@@ -185,22 +209,6 @@ class GoogleMapsViewImpl(
185209 )
186210 }
187211
188- @SuppressLint(" PotentialBehaviorOverride" )
189- override fun onMapReady (map : GoogleMap ) {
190- googleMap = map
191- googleMap?.setOnMapLoadedCallback {
192- googleMap?.setOnCameraMoveStartedListener(this )
193- googleMap?.setOnCameraMoveListener(this )
194- googleMap?.setOnCameraIdleListener(this )
195- googleMap?.setOnMarkerClickListener(this )
196- googleMap?.setOnMapClickListener(this )
197- }
198- initLocationCallbacks()
199- applyPending()
200-
201- onMapReady?.invoke(true )
202- }
203-
204212 fun initLocationCallbacks () {
205213 locationHandler.onUpdate = { location ->
206214 // / only the coordinated are relevant right now
@@ -225,38 +233,31 @@ class GoogleMapsViewImpl(
225233
226234 fun applyPending () {
227235 onUi {
228- pendingMapPadding ?.let {
236+ mapPadding ?.let {
229237 googleMap?.setPadding(
230238 it.left.dpToPx().toInt(),
231239 it.top.dpToPx().toInt(),
232240 it.right.dpToPx().toInt(),
233241 it.bottom.dpToPx().toInt(),
234242 )
235243 }
236- pendingInitialCamera?.let {
237- googleMap?.moveCamera(
238- CameraUpdateFactory .newCameraPosition(
239- it,
240- ),
241- )
242- }
243- pendingBuildingEnabled?.let {
244+ buildingEnabled?.let {
244245 googleMap?.isBuildingsEnabled = it
245246 }
246- pendingTrafficEnabled ?.let {
247+ trafficEnabled ?.let {
247248 googleMap?.isTrafficEnabled = it
248249 }
249- googleMap?.setMapStyle(pendingCustomMapStyle )
250- pendingMapType ?.let {
250+ googleMap?.setMapStyle(customMapStyle )
251+ mapType ?.let {
251252 googleMap?.mapType = it
252253 }
253- pendingUserInterfaceStyle ?.let {
254+ userInterfaceStyle ?.let {
254255 googleMap?.mapColorScheme = it
255256 }
256- pendingMinZoomLevel ?.let {
257+ minZoomLevel ?.let {
257258 googleMap?.setMinZoomPreference(it.toFloat())
258259 }
259- pendingMaxZoomLevel ?.let {
260+ maxZoomLevel ?.let {
260261 googleMap?.setMaxZoomPreference(it.toFloat())
261262 }
262263 }
@@ -283,10 +284,9 @@ class GoogleMapsViewImpl(
283284 }
284285 }
285286
286- var buildingEnabled: Boolean?
287- get() = googleMap?.isBuildingsEnabled ? : pendingBuildingEnabled
287+ var buildingEnabled: Boolean? = null
288288 set(value) {
289- pendingBuildingEnabled = value
289+ field = value
290290 onUi {
291291 value?.let {
292292 googleMap?.isBuildingsEnabled = it
@@ -297,10 +297,9 @@ class GoogleMapsViewImpl(
297297 }
298298 }
299299
300- var trafficEnabled: Boolean?
301- get() = googleMap?.isTrafficEnabled ? : pendingTrafficEnabled
300+ var trafficEnabled: Boolean? = null
302301 set(value) {
303- pendingTrafficEnabled = value
302+ field = value
304303 onUi {
305304 value?.let {
306305 googleMap?.isTrafficEnabled = it
@@ -310,25 +309,17 @@ class GoogleMapsViewImpl(
310309 }
311310 }
312311
313- var customMapStyle: MapStyleOptions ?
314- get() = pendingCustomMapStyle
312+ var customMapStyle: MapStyleOptions ? = null
315313 set(value) {
316- pendingCustomMapStyle = value
314+ field = value
317315 onUi {
318316 googleMap?.setMapStyle(value)
319317 }
320318 }
321319
322- var initialCamera: CameraPosition ?
323- get() = pendingInitialCamera
320+ var userInterfaceStyle: Int? = null
324321 set(value) {
325- pendingInitialCamera = value
326- }
327-
328- var userInterfaceStyle: Int?
329- get() = pendingUserInterfaceStyle
330- set(value) {
331- pendingUserInterfaceStyle = value
322+ field = value
332323 onUi {
333324 value?.let {
334325 googleMap?.mapColorScheme = it
@@ -338,10 +329,9 @@ class GoogleMapsViewImpl(
338329 }
339330 }
340331
341- var minZoomLevel: Double?
342- get() = pendingMinZoomLevel
332+ var minZoomLevel: Double? = null
343333 set(value) {
344- pendingMinZoomLevel = value
334+ field = value
345335 onUi {
346336 value?.let {
347337 googleMap?.setMinZoomPreference(it.toFloat())
@@ -351,10 +341,9 @@ class GoogleMapsViewImpl(
351341 }
352342 }
353343
354- var maxZoomLevel: Double?
355- get() = pendingMaxZoomLevel
344+ var maxZoomLevel: Double? = null
356345 set(value) {
357- pendingMaxZoomLevel = value
346+ field = value
358347 onUi {
359348 value?.let {
360349 googleMap?.setMaxZoomPreference(it.toFloat())
@@ -364,10 +353,9 @@ class GoogleMapsViewImpl(
364353 }
365354 }
366355
367- var mapPadding: RNMapPadding ?
368- get() = pendingMapPadding
356+ var mapPadding: RNMapPadding ? = null
369357 set(value) {
370- pendingMapPadding = value
358+ field = value
371359 value?.let {
372360 onUi {
373361 googleMap?.setPadding(
@@ -382,10 +370,9 @@ class GoogleMapsViewImpl(
382370 }
383371 }
384372
385- var mapType: Int?
386- get() = pendingMapType
373+ var mapType: Int? = null
387374 set(value) {
388- pendingMapType = value
375+ field = value
389376 onUi {
390377 value?.let {
391378 googleMap?.mapType = it
@@ -470,8 +457,8 @@ class GoogleMapsViewImpl(
470457 val latSpan = bounds.northeast.latitude - bounds.southwest.latitude
471458 val lngSpan = bounds.northeast.longitude - bounds.southwest.longitude
472459
473- val latPerPixel = latSpan / height
474- val lngPerPixel = lngSpan / width
460+ val latPerPixel = latSpan / (mapView?. height ? : 0 )
461+ val lngPerPixel = lngSpan / (mapView?. width ? : 0 )
475462
476463 builder.include(
477464 LatLng (
@@ -500,8 +487,10 @@ class GoogleMapsViewImpl(
500487
501488 val paddedBounds = builder.build()
502489
503- val adjustedWidth = (width - padding.left.dpToPx() - padding.right.dpToPx()).toInt()
504- val adjustedHeight = (height - padding.top.dpToPx() - padding.bottom.dpToPx()).toInt()
490+ val adjustedWidth =
491+ ((mapView?.width ? : 0 ) - padding.left.dpToPx() - padding.right.dpToPx()).toInt()
492+ val adjustedHeight =
493+ ((mapView?.height ? : 0 ) - padding.top.dpToPx() - padding.bottom.dpToPx()).toInt()
505494
506495 val update =
507496 CameraUpdateFactory .newLatLngBounds(
@@ -680,7 +669,7 @@ class GoogleMapsViewImpl(
680669 pendingPolygons.clear()
681670 }
682671
683- fun clearAll () {
672+ fun destroyInternal () {
684673 onUi {
685674 markerOptions.cancelAllJobs()
686675 clearMarkers()
@@ -694,8 +683,14 @@ class GoogleMapsViewImpl(
694683 setOnMarkerClickListener(null )
695684 setOnMapClickListener(null )
696685 }
697- this @GoogleMapsViewImpl.onDestroy()
698686 googleMap = null
687+ mapView?.apply {
688+ onPause()
689+ onStop()
690+ onDestroy()
691+ removeAllViews()
692+ }
693+ super .removeAllViews()
699694 reactContext.removeLifecycleEventListener(this )
700695 }
701696 }
@@ -725,19 +720,19 @@ class GoogleMapsViewImpl(
725720 override fun onHostResume () {
726721 onUi {
727722 locationHandler.start()
728- this @GoogleMapsViewImpl .onResume()
723+ mapView? .onResume()
729724 }
730725 }
731726
732727 override fun onHostPause () {
733728 onUi {
734729 locationHandler.stop()
735- this @GoogleMapsViewImpl .onPause()
730+ mapView? .onPause()
736731 }
737732 }
738733
739734 override fun onHostDestroy () {
740- clearAll ()
735+ destroyInternal ()
741736 }
742737
743738 override fun onMarkerClick (marker : Marker ): Boolean {
0 commit comments