Skip to content

[Feature request]: Add a way to prevent camera updates when padding changes on iOS (as on Android) #660

@bderrien

Description

@bderrien

Is there an existing issue for this?

  • I have searched the existing issues

Use case

When setting new padding on the map, I don’t want the camera position to update and recenter based on the new padding (as on Android).

Proposal

here is my proposal option :

diff --git forkSrcPrefix/ios/google_navigation_flutter/Sources/google_navigation_flutter/MapConfiguration.swift forkDstPrefix/ios/google_navigation_flutter/Sources/google_navigation_flutter/MapConfiguration.swift
index 2a0ae04795069f31eff38b41fe376f22849c8c57..a50d5e14934604c0c2cb39f99c9b142045d48750 100644
--- forkSrcPrefix/ios/google_navigation_flutter/Sources/google_navigation_flutter/MapConfiguration.swift
+++ forkDstPrefix/ios/google_navigation_flutter/Sources/google_navigation_flutter/MapConfiguration.swift
@@ -15,6 +15,30 @@
 import Foundation
 import GoogleMaps
 
+extension GMSMapView {
+  /// Applies padding and compensates with `scrollBy` so the map does not appear to jump:
+  /// the SDK draws `camera.target` at the padded content center, which moves when insets change.
+  func applyPaddingPreservingCamera(_ padding: UIEdgeInsets) {
+    let oldPadding = self.padding
+    let b = bounds
+    let oldContent = b.inset(by: oldPadding)
+    let newContent = b.inset(by: padding)
+    let oldCenter = CGPoint(x: oldContent.midX, y: oldContent.midY)
+    let newCenter = CGPoint(x: newContent.midX, y: newContent.midY)
+    // `scrollBy` sign: positive x/y move the camera right/down (map appears left/up).
+    let scrollX = newCenter.x - oldCenter.x
+    let scrollY = newCenter.y - oldCenter.y
+
+    self.padding = padding
+
+    let validOld = oldContent.width > 0 && oldContent.height > 0
+    let validNew = newContent.width > 0 && newContent.height > 0
+    if b.width > 0, b.height > 0, validOld, validNew, scrollX != 0 || scrollY != 0 {
+      moveCamera(GMSCameraUpdate.scrollBy(x: scrollX, y: scrollY))
+    }
+  }
+}
+
 // Determines the initial visibility of the navigation UI on map initialization.
 enum NavigationUIEnabledPreference {
   // Navigation UI gets enabled if the navigation
@@ -62,7 +86,7 @@ extension MapConfiguration {
       maxZoom: maxZoomPreference ?? kGMSMaxZoomLevel
     )
     if let padding {
-      mapView.padding = padding
+      mapView.applyPaddingPreservingCamera(padding)
     }
   }
 
diff --git forkSrcPrefix/ios/google_navigation_flutter/Sources/google_navigation_flutter/GoogleMapsNavigationView.swift forkDstPrefix/ios/google_navigation_flutter/Sources/google_navigation_flutter/GoogleMapsNavigationView.swift
index 809c3bd59757e5c13ee2b29736da6dcf4bd9c9a2..b00040d989c212aebcc698e02709fee1cf8e8853 100644
--- forkSrcPrefix/ios/google_navigation_flutter/Sources/google_navigation_flutter/GoogleMapsNavigationView.swift
+++ forkDstPrefix/ios/google_navigation_flutter/Sources/google_navigation_flutter/GoogleMapsNavigationView.swift
@@ -941,12 +941,13 @@ public class GoogleMapsNavigationView: NSObject, FlutterPlatformView, ViewSettle
   }
 
   func setPadding(padding: MapPaddingDto) throws {
-    _mapView.padding = UIEdgeInsets(
+    let insets = UIEdgeInsets(
       top: CGFloat(padding.top),
       left: CGFloat(padding.left),
       bottom: CGFloat(padding.bottom),
       right: CGFloat(padding.right)
     )
+    _mapView.applyPaddingPreservingCamera(insets)
   }
 
   func getPadding() throws -> MapPaddingDto {

Metadata

Metadata

Assignees

Labels

triage meI really want to be triaged.type: feature request‘Nice-to-have’ improvement, new feature or different behavior or design.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions