diff --git a/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md index 095e04709027..50ca4a9e6894 100644 --- a/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md @@ -1,6 +1,11 @@ -## NEXT - -* Updates minimum supported SDK version to Flutter 3.13/Dart 3.1. +## 2.6.0 + +* Adds `style` to the GoogleMap widget constructor. This allows setting the map + style during creation, avoiding the possibility of the default style being + displayed briefly. +* Deprecates `GoogleMapController.setMapStyle` in favor of setting the style via + the new widget `style` parameter. +* Updates minimum supported SDK version to Flutter 3.19. ## 2.5.3 diff --git a/packages/google_maps_flutter/google_maps_flutter/example/integration_test/src/maps_controller.dart b/packages/google_maps_flutter/google_maps_flutter/example/integration_test/src/maps_controller.dart index 01716232814e..3d99369e33be 100644 --- a/packages/google_maps_flutter/google_maps_flutter/example/integration_test/src/maps_controller.dart +++ b/packages/google_maps_flutter/google_maps_flutter/example/integration_test/src/maps_controller.dart @@ -448,6 +448,28 @@ void runTests() { await mapIdCompleter.future; }, ); + + testWidgets('getStyleError reports last error', (WidgetTester tester) async { + final Key key = GlobalKey(); + final Completer controllerCompleter = + Completer(); + + await pumpMap( + tester, + GoogleMap( + key: key, + initialCameraPosition: kInitialCameraPosition, + style: '[[[this is an invalid style', + onMapCreated: (GoogleMapController controller) { + controllerCompleter.complete(controller); + }, + ), + ); + + final GoogleMapController controller = await controllerCompleter.future; + final String? error = await controller.getStyleError(); + expect(error, isNotNull); + }); } /// Repeatedly checks an asynchronous value against a test condition. diff --git a/packages/google_maps_flutter/google_maps_flutter/example/lib/map_ui.dart b/packages/google_maps_flutter/google_maps_flutter/example/lib/map_ui.dart index 5348c1001af7..26c0b2ab720a 100644 --- a/packages/google_maps_flutter/google_maps_flutter/example/lib/map_ui.dart +++ b/packages/google_maps_flutter/google_maps_flutter/example/lib/map_ui.dart @@ -4,6 +4,7 @@ // ignore_for_file: public_member_api_docs +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart' show rootBundle; import 'package:google_maps_flutter/google_maps_flutter.dart'; @@ -59,6 +60,7 @@ class MapUiBodyState extends State { bool _myLocationButtonEnabled = true; late GoogleMapController _controller; bool _nightMode = false; + String _mapStyle = ''; @override void initState() { @@ -243,27 +245,18 @@ class MapUiBodyState extends State { return rootBundle.loadString(path); } - void _setMapStyle(String mapStyle) { - setState(() { - _nightMode = true; - _controller.setMapStyle(mapStyle); - }); - } - // Should only be called if _isMapCreated is true. Widget _nightModeToggler() { assert(_isMapCreated); return TextButton( child: Text('${_nightMode ? 'disable' : 'enable'} night mode'), - onPressed: () { - if (_nightMode) { - setState(() { - _nightMode = false; - _controller.setMapStyle(null); - }); - } else { - _getFileData('assets/night_mode.json').then(_setMapStyle); - } + onPressed: () async { + _nightMode = !_nightMode; + final String style = + _nightMode ? await _getFileData('assets/night_mode.json') : ''; + setState(() { + _mapStyle = style; + }); }, ); } @@ -278,6 +271,7 @@ class MapUiBodyState extends State { cameraTargetBounds: _cameraTargetBounds, minMaxZoomPreference: _minMaxZoomPreference, mapType: _mapType, + style: _mapStyle, rotateGesturesEnabled: _rotateGesturesEnabled, scrollGesturesEnabled: _scrollGesturesEnabled, tiltGesturesEnabled: _tiltGesturesEnabled, @@ -352,5 +346,13 @@ class MapUiBodyState extends State { _controller = controller; _isMapCreated = true; }); + // Log any style errors to the console for debugging. + if (kDebugMode) { + _controller.getStyleError().then((String? error) { + if (error != null) { + debugPrint(error); + } + }); + } } } diff --git a/packages/google_maps_flutter/google_maps_flutter/example/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter/example/pubspec.yaml index efed14ceecbf..ba306fd8bd9e 100644 --- a/packages/google_maps_flutter/google_maps_flutter/example/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter/example/pubspec.yaml @@ -19,7 +19,7 @@ dependencies: # the parent directory to use the current plugin's version. path: ../ google_maps_flutter_android: ^2.5.0 - google_maps_flutter_platform_interface: ^2.4.0 + google_maps_flutter_platform_interface: ^2.5.0 dev_dependencies: build_runner: ^2.1.10 diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/controller.dart b/packages/google_maps_flutter/google_maps_flutter/lib/src/controller.dart index 095d15867acc..393288a6165f 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/controller.dart +++ b/packages/google_maps_flutter/google_maps_flutter/lib/src/controller.dart @@ -190,11 +190,17 @@ class GoogleMapController { /// Also, refer [iOS](https://developers.google.com/maps/documentation/ios-sdk/style-reference) /// and [Android](https://developers.google.com/maps/documentation/android-sdk/style-reference) /// style reference for more information regarding the supported styles. + @Deprecated('Use GoogleMap.style instead.') Future setMapStyle(String? mapStyle) { return GoogleMapsFlutterPlatform.instance .setMapStyle(mapStyle, mapId: mapId); } + /// Returns the last style error, if any. + Future getStyleError() { + return GoogleMapsFlutterPlatform.instance.getStyleError(mapId: mapId); + } + /// Return [LatLngBounds] defining the region that is visible in a map. Future getVisibleRegion() { return GoogleMapsFlutterPlatform.instance.getVisibleRegion(mapId: mapId); diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/google_map.dart b/packages/google_maps_flutter/google_maps_flutter/lib/src/google_map.dart index 3b73e55664dd..c50ffccfa634 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/google_map.dart +++ b/packages/google_maps_flutter/google_maps_flutter/lib/src/google_map.dart @@ -91,6 +91,7 @@ class GoogleMap extends StatefulWidget { const GoogleMap({ super.key, required this.initialCameraPosition, + this.style, this.onMapCreated, this.gestureRecognizers = const >{}, this.webGestureHandling, @@ -136,6 +137,19 @@ class GoogleMap extends StatefulWidget { /// The initial position of the map's camera. final CameraPosition initialCameraPosition; + /// The style for the map. + /// + /// Set to null to clear any previous custom styling. + /// + /// If problems were detected with the [mapStyle], including un-parsable + /// styling JSON, unrecognized feature type, unrecognized element type, or + /// invalid styler keys, the style is left unchanged, and the error can be + /// retrieved with [GoogleMapController.getStyleError]. + /// + /// The style string can be generated using the + /// [map style tool](https://mapstyle.withgoogle.com/). + final String? style; + /// True if the map should show a compass when rotated. final bool compassEnabled; @@ -556,5 +570,8 @@ MapConfiguration _configurationFromMapWidget(GoogleMap map) { trafficEnabled: map.trafficEnabled, buildingsEnabled: map.buildingsEnabled, cloudMapId: map.cloudMapId, + // A null style in the widget means no style, which is expressed as '' in + // the configuration to distinguish from no change (null). + style: map.style ?? '', ); } diff --git a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml index 9b53f596fdf6..598ab6f7aeb6 100644 --- a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml @@ -2,11 +2,11 @@ name: google_maps_flutter description: A Flutter plugin for integrating Google Maps in iOS and Android applications. repository: https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22 -version: 2.5.3 +version: 2.6.0 environment: - sdk: ^3.1.0 - flutter: ">=3.13.0" + sdk: ^3.3.0 + flutter: ">=3.19.0" flutter: plugin: @@ -21,10 +21,10 @@ flutter: dependencies: flutter: sdk: flutter - google_maps_flutter_android: ^2.5.0 - google_maps_flutter_ios: ^2.3.0 - google_maps_flutter_platform_interface: ^2.4.0 - google_maps_flutter_web: ^0.5.2 + google_maps_flutter_android: ^2.7.0 + google_maps_flutter_ios: ^2.5.0 + google_maps_flutter_platform_interface: ^2.5.0 + google_maps_flutter_web: ^0.5.6 dev_dependencies: flutter_test: diff --git a/packages/google_maps_flutter/google_maps_flutter/test/google_map_test.dart b/packages/google_maps_flutter/google_maps_flutter/test/google_map_test.dart index 7005a8d3ab60..9276a7dbda30 100644 --- a/packages/google_maps_flutter/google_maps_flutter/test/google_map_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter/test/google_map_test.dart @@ -551,4 +551,32 @@ void main() { expect(map.mapConfiguration.buildingsEnabled, true); }); + + testWidgets('Can update style', (WidgetTester tester) async { + const String initialStyle = '[]'; + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: GoogleMap( + initialCameraPosition: CameraPosition(target: LatLng(10.0, 15.0)), + style: initialStyle, + ), + ), + ); + + final PlatformMapStateRecorder map = platform.lastCreatedMap; + + expect(map.mapConfiguration.style, initialStyle); + + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: GoogleMap( + initialCameraPosition: CameraPosition(target: LatLng(10.0, 15.0)), + ), + ), + ); + + expect(map.mapConfiguration.style, ''); + }); }