diff --git a/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md index 5b3e35097f34..bdc8a7372c76 100644 --- a/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.5.26+3 + +* iOS: observe the bounds update for the `GMSMapView` to reset the camera setting. +* Update UI related e2e tests to wait for camera update on the platform thread. + ## 0.5.26+2 * Fix UIKit availability warnings and CocoaPods podspec lint warnings. diff --git a/packages/google_maps_flutter/google_maps_flutter/example/test_driver/google_maps_e2e.dart b/packages/google_maps_flutter/google_maps_flutter/example/test_driver/google_maps_e2e.dart index 3b78d2f975a7..2eccbc4beba6 100644 --- a/packages/google_maps_flutter/google_maps_flutter/example/test_driver/google_maps_e2e.dart +++ b/packages/google_maps_flutter/google_maps_flutter/example/test_driver/google_maps_e2e.dart @@ -383,6 +383,53 @@ void main() { expect(scrollGesturesEnabled, true); }); + testWidgets('testInitialCenterLocationAtCenter', (WidgetTester tester) async { + final Completer mapControllerCompleter = + Completer(); + final Key key = GlobalKey(); + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: GoogleMap( + key: key, + initialCameraPosition: _kInitialCameraPosition, + onMapCreated: (GoogleMapController controller) { + mapControllerCompleter.complete(controller); + }, + ), + ), + ); + final GoogleMapController mapController = + await mapControllerCompleter.future; + + await tester.pumpAndSettle(); + // TODO(cyanglaz): Remove this after we added `mapRendered` callback, and `mapControllerCompleter.complete(controller)` above should happen + // in `mapRendered`. + // https://github.com/flutter/flutter/issues/54758 + await Future.delayed(Duration(seconds: 1)); + + ScreenCoordinate coordinate = + await mapController.getScreenCoordinate(_kInitialCameraPosition.target); + Rect rect = tester.getRect(find.byKey(key)); + if (Platform.isIOS) { + // On iOS, the coordinate value from the GoogleMapSdk doesn't include the devicePixelRatio`. + // So we don't need to do the conversion like we did below for other platforms. + expect(coordinate.x, (rect.center.dx - rect.topLeft.dx).round()); + expect(coordinate.y, (rect.center.dy - rect.topLeft.dy).round()); + } else { + expect( + coordinate.x, + ((rect.center.dx - rect.topLeft.dx) * + tester.binding.window.devicePixelRatio) + .round()); + expect( + coordinate.y, + ((rect.center.dy - rect.topLeft.dy) * + tester.binding.window.devicePixelRatio) + .round()); + } + }); + testWidgets('testGetVisibleRegion', (WidgetTester tester) async { final Key key = GlobalKey(); final LatLngBounds zeroLatLngBounds = LatLngBounds( @@ -401,13 +448,8 @@ void main() { }, ), )); - // We suspected a bug in the iOS Google Maps SDK caused the camera is not properly positioned at - // initialization. https://github.com/flutter/flutter/issues/24806 - // This temporary workaround fix is provided while the actual fix in the Google Maps SDK is - // still being investigated. - // TODO(cyanglaz): Remove this temporary fix once the Maps SDK issue is resolved. - // https://github.com/flutter/flutter/issues/27550 - await tester.pumpAndSettle(const Duration(seconds: 3)); + await tester.pumpAndSettle(); + final GoogleMapController mapController = await mapControllerCompleter.future; @@ -707,13 +749,11 @@ void main() { final GoogleMapController controller = await controllerCompleter.future; - // We suspected a bug in the iOS Google Maps SDK caused the camera is not properly positioned at - // initialization. https://github.com/flutter/flutter/issues/24806 - // This temporary workaround fix is provided while the actual fix in the Google Maps SDK is - // still being investigated. - // TODO(cyanglaz): Remove this temporary fix once the Maps SDK issue is resolved. - // https://github.com/flutter/flutter/issues/27550 - await tester.pumpAndSettle(const Duration(seconds: 3)); + await tester.pumpAndSettle(); + // TODO(cyanglaz): Remove this after we added `mapRendered` callback, and `mapControllerCompleter.complete(controller)` above should happen + // in `mapRendered`. + // https://github.com/flutter/flutter/issues/54758 + await Future.delayed(Duration(seconds: 1)); final LatLngBounds visibleRegion = await controller.getVisibleRegion(); final LatLng topLeft = @@ -744,13 +784,11 @@ void main() { final GoogleMapController controller = await controllerCompleter.future; - // We suspected a bug in the iOS Google Maps SDK caused the camera is not properly positioned at - // initialization. https://github.com/flutter/flutter/issues/24806 - // This temporary workaround fix is provided while the actual fix in the Google Maps SDK is - // still being investigated. - // TODO(cyanglaz): Remove this temporary fix once the Maps SDK issue is resolved. - // https://github.com/flutter/flutter/issues/27550 - await tester.pumpAndSettle(const Duration(seconds: 3)); + await tester.pumpAndSettle(); + // TODO(cyanglaz): Remove this after we added `mapRendered` callback, and `mapControllerCompleter.complete(controller)` above should happen + // in `mapRendered`. + // https://github.com/flutter/flutter/issues/54758 + await Future.delayed(Duration(seconds: 1)); double zoom = await controller.getZoomLevel(); expect(zoom, _kInitialZoomLevel); @@ -778,13 +816,11 @@ void main() { )); final GoogleMapController controller = await controllerCompleter.future; - // We suspected a bug in the iOS Google Maps SDK caused the camera is not properly positioned at - // initialization. https://github.com/flutter/flutter/issues/24806 - // This temporary workaround fix is provided while the actual fix in the Google Maps SDK is - // still being investigated. - // TODO(cyanglaz): Remove this temporary fix once the Maps SDK issue is resolved. - // https://github.com/flutter/flutter/issues/27550 - await tester.pumpAndSettle(const Duration(seconds: 3)); + await tester.pumpAndSettle(); + // TODO(cyanglaz): Remove this after we added `mapRendered` callback, and `mapControllerCompleter.complete(controller)` above should happen + // in `mapRendered`. + // https://github.com/flutter/flutter/issues/54758 + await Future.delayed(Duration(seconds: 1)); final LatLngBounds visibleRegion = await controller.getVisibleRegion(); final LatLng northWest = LatLng( @@ -818,13 +854,11 @@ void main() { home: Scaffold( body: SizedBox(height: 400, width: 400, child: map))))); - // We suspected a bug in the iOS Google Maps SDK caused the camera is not properly positioned at - // initialization. https://github.com/flutter/flutter/issues/24806 - // This temporary workaround fix is provided while the actual fix in the Google Maps SDK is - // still being investigated. - // TODO(cyanglaz): Remove this temporary fix once the Maps SDK issue is resolved. - // https://github.com/flutter/flutter/issues/27550 - await tester.pumpAndSettle(const Duration(seconds: 3)); + await tester.pumpAndSettle(); + // TODO(cyanglaz): Remove this after we added `mapRendered` callback, and `mapControllerCompleter.complete(controller)` above should happen + // in `mapRendered`. + // https://github.com/flutter/flutter/issues/54758 + await Future.delayed(Duration(seconds: 1)); // Simple call to make sure that the app hasn't crashed. final LatLngBounds bounds1 = await controller.getVisibleRegion(); diff --git a/packages/google_maps_flutter/google_maps_flutter/ios/Classes/GoogleMapController.m b/packages/google_maps_flutter/google_maps_flutter/ios/Classes/GoogleMapController.m index 59bfaa01f04d..321ddd318536 100644 --- a/packages/google_maps_flutter/google_maps_flutter/ios/Classes/GoogleMapController.m +++ b/packages/google_maps_flutter/google_maps_flutter/ios/Classes/GoogleMapController.m @@ -50,10 +50,6 @@ @implementation FLTGoogleMapController { FlutterMethodChannel* _channel; BOOL _trackCameraPosition; NSObject* _registrar; - // Used for the temporary workaround for a bug that the camera is not properly positioned at - // initialization. https://github.com/flutter/flutter/issues/24806 - // TODO(cyanglaz): Remove this temporary fix once the Maps SDK issue is resolved. - // https://github.com/flutter/flutter/issues/27550 BOOL _cameraDidInitialSetup; FLTMarkersController* _markersController; FLTPolygonsController* _polygonsController; @@ -119,9 +115,36 @@ - (instancetype)initWithFrame:(CGRect)frame } - (UIView*)view { + [_mapView addObserver:self forKeyPath:@"frame" options:0 context:nil]; return _mapView; } +- (void)observeValueForKeyPath:(NSString*)keyPath + ofObject:(id)object + change:(NSDictionary*)change + context:(void*)context { + if (_cameraDidInitialSetup) { + // We only observe the frame for initial setup. + [_mapView removeObserver:self forKeyPath:@"frame"]; + return; + } + if (object == _mapView && [keyPath isEqualToString:@"frame"]) { + CGRect bounds = _mapView.bounds; + if (CGRectEqualToRect(bounds, CGRectZero)) { + // The workaround is to fix an issue that the camera location is not current when + // the size of the map is zero at initialization. + // So We only care about the size of the `_mapView`, ignore the frame changes when the size is + // zero. + return; + } + _cameraDidInitialSetup = YES; + [_mapView removeObserver:self forKeyPath:@"frame"]; + [_mapView moveCamera:[GMSCameraUpdate setCamera:_mapView.camera]]; + } else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + - (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { if ([call.method isEqualToString:@"map#show"]) { [self showAtX:ToDouble(call.arguments[@"x"]) Y:ToDouble(call.arguments[@"y"])]; @@ -437,16 +460,6 @@ - (void)mapView:(GMSMapView*)mapView willMove:(BOOL)gesture { } - (void)mapView:(GMSMapView*)mapView didChangeCameraPosition:(GMSCameraPosition*)position { - if (!_cameraDidInitialSetup) { - // We suspected a bug in the iOS Google Maps SDK caused the camera is not properly positioned at - // initialization. https://github.com/flutter/flutter/issues/24806 - // This temporary workaround fix is provided while the actual fix in the Google Maps SDK is - // still being investigated. - // TODO(cyanglaz): Remove this temporary fix once the Maps SDK issue is resolved. - // https://github.com/flutter/flutter/issues/27550 - _cameraDidInitialSetup = YES; - [mapView moveCamera:[GMSCameraUpdate setCamera:_mapView.camera]]; - } if (_trackCameraPosition) { [_channel invokeMethod:@"camera#onMove" arguments:@{@"position" : PositionToJson(position)}]; } @@ -511,8 +524,8 @@ - (void)mapView:(GMSMapView*)mapView didLongPressAtCoordinate:(CLLocationCoordin static NSDictionary* PointToJson(CGPoint point) { return @{ - @"x" : @((int)point.x), - @"y" : @((int)point.y), + @"x" : @(lroundf(point.x)), + @"y" : @(lroundf(point.y)), }; } diff --git a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml index 3d5f7b5cd1ba..8c50efcc3c48 100644 --- a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml @@ -1,7 +1,7 @@ name: google_maps_flutter description: A Flutter plugin for integrating Google Maps in iOS and Android applications. homepage: https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter -version: 0.5.26+2 +version: 0.5.26+3 dependencies: flutter: