@lugg/maps 1.0.0-beta.20 → 1.0.0-beta.21

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.
@@ -5,6 +5,7 @@ import android.content.ComponentCallbacks2
5
5
  import android.content.Context
6
6
  import android.content.res.Configuration
7
7
  import android.view.View
8
+ import android.view.ViewTreeObserver
8
9
  import android.widget.ImageView
9
10
  import androidx.core.graphics.createBitmap
10
11
  import androidx.core.view.ViewCompat
@@ -135,6 +136,13 @@ class GoogleMapProvider(private val context: Context) :
135
136
  private var insetAdjustment: String = "never"
136
137
  private var systemInsets: EdgeInsets = EdgeInsets()
137
138
 
139
+ // The maps renderer adds and positions the watermark asynchronously; the
140
+ // layout listener re-evaluates the translation on every layout pass
141
+ private var watermarkLayoutListener: ViewTreeObserver.OnGlobalLayoutListener? = null
142
+ private var watermarkView: View? = null
143
+ private var watermarkTargetX = 0f
144
+ private var watermarkTargetY = 0f
145
+
138
146
  // region MapProvider
139
147
 
140
148
  override fun initializeMap(wrapperView: View, latitude: Double, longitude: Double, zoom: Float) {
@@ -183,6 +191,7 @@ class GoogleMapProvider(private val context: Context) :
183
191
  override fun destroy() {
184
192
  wrapperView?.onLayoutReady = null
185
193
  detachWindowInsetsListener()
194
+ detachWatermarkLayoutListener()
186
195
  context.applicationContext.unregisterComponentCallbacks(this)
187
196
  dismissNonBubbledCallout()
188
197
  for (markerView in liveMarkerViews) {
@@ -237,6 +246,11 @@ class GoogleMapProvider(private val context: Context) :
237
246
  }
238
247
  }
239
248
 
249
+ // Padding must be in place before the initial camera move: setPadding
250
+ // never repositions the current camera, but camera updates after it are
251
+ // relative to the padded center
252
+ applyEdgeInsets()
253
+
240
254
  val position = if (staticMode) staticCameraTarget() else LatLng(initialLatitude, initialLongitude)
241
255
  map.moveCamera(CameraUpdateFactory.newLatLngZoom(position, initialZoom))
242
256
 
@@ -260,7 +274,6 @@ class GoogleMapProvider(private val context: Context) :
260
274
 
261
275
  applyUiSettings()
262
276
  applyZoomLimits()
263
- applyEdgeInsets()
264
277
  applyInsetAdjustment()
265
278
  applyTheme()
266
279
  applyUserLocation()
@@ -1430,27 +1443,74 @@ class GoogleMapProvider(private val context: Context) :
1430
1443
  // World size in px at the given zoom
1431
1444
  private fun mercatorWorldSize(zoom: Float): Double = 256f.dpToPx().toDouble() * 2.0.pow(zoom.toDouble())
1432
1445
 
1446
+ // Whether the renderer repositions the watermark for setPadding varies by
1447
+ // renderer version and by whether the watermark existed when padding was
1448
+ // set (and lite mode never applies padding). Measure where layout actually
1449
+ // placed it and translate only for the remainder.
1433
1450
  private fun applyWatermarkTranslation(insets: EdgeInsets, duration: Int = 0) {
1434
1451
  val view = mapView ?: return
1435
- view.findViewByTag("GoogleWatermark")?.let { watermark ->
1436
- val targetY = -insets.bottom.toFloat()
1437
- val targetX = insets.left.toFloat()
1438
- if (duration > 0) {
1439
- watermark.animate()
1440
- .translationY(targetY)
1441
- .translationX(targetX)
1442
- .setDuration(duration.toLong())
1443
- .start()
1444
- } else if (duration < 0) {
1445
- watermark.animate()
1446
- .translationY(targetY)
1447
- .translationX(targetX)
1448
- .start()
1449
- } else {
1450
- watermark.translationY = targetY
1451
- watermark.translationX = targetX
1452
- }
1452
+ attachWatermarkLayoutListener()
1453
+
1454
+ if (view.height == 0) return
1455
+ val watermark = view.findViewByTag("GoogleWatermark") ?: return
1456
+
1457
+ // Layout position relative to the map view, excluding translation
1458
+ var left = 0
1459
+ var top = 0
1460
+ var current: View? = watermark
1461
+ while (current != null && current !== view) {
1462
+ left += current.left
1463
+ top += current.top
1464
+ current = current.parent as? View
1453
1465
  }
1466
+ if (current == null) return
1467
+
1468
+ val bottomGap = view.height - (top + watermark.height)
1469
+ val targetY = if (bottomGap >= insets.bottom) 0f else -insets.bottom.toFloat()
1470
+ val targetX = if (left >= insets.left) 0f else insets.left.toFloat()
1471
+
1472
+ // Skip when already applied (or animating) toward this target so layout
1473
+ // passes don't snap an in-flight animation
1474
+ if (watermark === watermarkView && targetX == watermarkTargetX && targetY == watermarkTargetY) {
1475
+ return
1476
+ }
1477
+ watermarkView = watermark
1478
+ watermarkTargetX = targetX
1479
+ watermarkTargetY = targetY
1480
+
1481
+ if (duration > 0) {
1482
+ watermark.animate()
1483
+ .translationY(targetY)
1484
+ .translationX(targetX)
1485
+ .setDuration(duration.toLong())
1486
+ .start()
1487
+ } else if (duration < 0) {
1488
+ watermark.animate()
1489
+ .translationY(targetY)
1490
+ .translationX(targetX)
1491
+ .start()
1492
+ } else {
1493
+ watermark.translationY = targetY
1494
+ watermark.translationX = targetX
1495
+ }
1496
+ }
1497
+
1498
+ private fun attachWatermarkLayoutListener() {
1499
+ if (watermarkLayoutListener != null) return
1500
+ val view = mapView ?: return
1501
+
1502
+ val listener = ViewTreeObserver.OnGlobalLayoutListener {
1503
+ applyWatermarkTranslation(combinedEdgeInsets())
1504
+ }
1505
+ watermarkLayoutListener = listener
1506
+ view.viewTreeObserver.addOnGlobalLayoutListener(listener)
1507
+ }
1508
+
1509
+ private fun detachWatermarkLayoutListener() {
1510
+ watermarkView = null
1511
+ val listener = watermarkLayoutListener ?: return
1512
+ watermarkLayoutListener = null
1513
+ mapView?.viewTreeObserver?.takeIf { it.isAlive }?.removeOnGlobalLayoutListener(listener)
1454
1514
  }
1455
1515
 
1456
1516
  private fun attachWindowInsetsListener() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lugg/maps",
3
- "version": "1.0.0-beta.20",
3
+ "version": "1.0.0-beta.21",
4
4
  "description": "Universal maps for React Native.",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",