Skip to content

Commit 930318a

Browse files
[google_maps_flutter] Add style to widget (#6192)
Adds `style` to the `GoogleMap` widget construction, and internally to the `MapConfiguration` structure, wiring updates to style through the existing configuration update system instead of needing to be set via a separate channel. This makes things more consistent (style is conceptually similar to many of the other configuration options, and is not something that's likely to require frequent dynamic updates), and more importantly allows setting the style as part of creation instead of asynchronously after the map has likely already been displayed. Because of flutter/flutter#24327, this adds a way to query for style errors after the fact. (It's possible that it's why `setMapStyle` was done that way in the first place; the initial PR doesn't explain.) While this is slightly clunky, it's unlikely that this method would actually be used in production code anyway, since presumably people are defining their styles at build time, not runtime, and thus probably don't need runtime error handling. Long term, the solution to this problem is likely to invert the widget/controller relationship, as was done in webview_flutter, but that's a major breaking change and not something we're ready to take on at this point. Since we don't really want two recommended ways of doing the same thing, this deprecates the existing `setMapStyle` method in favor of the new approach. Fixes flutter/flutter#66207
1 parent ccec918 commit 930318a

File tree

8 files changed

+107
-27
lines changed

8 files changed

+107
-27
lines changed

packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
## NEXT
2-
3-
* Updates minimum supported SDK version to Flutter 3.13/Dart 3.1.
1+
## 2.6.0
2+
3+
* Adds `style` to the GoogleMap widget constructor. This allows setting the map
4+
style during creation, avoiding the possibility of the default style being
5+
displayed briefly.
6+
* Deprecates `GoogleMapController.setMapStyle` in favor of setting the style via
7+
the new widget `style` parameter.
8+
* Updates minimum supported SDK version to Flutter 3.19.
49

510
## 2.5.3
611

packages/google_maps_flutter/google_maps_flutter/example/integration_test/src/maps_controller.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,28 @@ void runTests() {
448448
await mapIdCompleter.future;
449449
},
450450
);
451+
452+
testWidgets('getStyleError reports last error', (WidgetTester tester) async {
453+
final Key key = GlobalKey();
454+
final Completer<GoogleMapController> controllerCompleter =
455+
Completer<GoogleMapController>();
456+
457+
await pumpMap(
458+
tester,
459+
GoogleMap(
460+
key: key,
461+
initialCameraPosition: kInitialCameraPosition,
462+
style: '[[[this is an invalid style',
463+
onMapCreated: (GoogleMapController controller) {
464+
controllerCompleter.complete(controller);
465+
},
466+
),
467+
);
468+
469+
final GoogleMapController controller = await controllerCompleter.future;
470+
final String? error = await controller.getStyleError();
471+
expect(error, isNotNull);
472+
});
451473
}
452474

453475
/// Repeatedly checks an asynchronous value against a test condition.

packages/google_maps_flutter/google_maps_flutter/example/lib/map_ui.dart

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
// ignore_for_file: public_member_api_docs
66

7+
import 'package:flutter/foundation.dart';
78
import 'package:flutter/material.dart';
89
import 'package:flutter/services.dart' show rootBundle;
910
import 'package:google_maps_flutter/google_maps_flutter.dart';
@@ -59,6 +60,7 @@ class MapUiBodyState extends State<MapUiBody> {
5960
bool _myLocationButtonEnabled = true;
6061
late GoogleMapController _controller;
6162
bool _nightMode = false;
63+
String _mapStyle = '';
6264

6365
@override
6466
void initState() {
@@ -243,27 +245,18 @@ class MapUiBodyState extends State<MapUiBody> {
243245
return rootBundle.loadString(path);
244246
}
245247

246-
void _setMapStyle(String mapStyle) {
247-
setState(() {
248-
_nightMode = true;
249-
_controller.setMapStyle(mapStyle);
250-
});
251-
}
252-
253248
// Should only be called if _isMapCreated is true.
254249
Widget _nightModeToggler() {
255250
assert(_isMapCreated);
256251
return TextButton(
257252
child: Text('${_nightMode ? 'disable' : 'enable'} night mode'),
258-
onPressed: () {
259-
if (_nightMode) {
260-
setState(() {
261-
_nightMode = false;
262-
_controller.setMapStyle(null);
263-
});
264-
} else {
265-
_getFileData('assets/night_mode.json').then(_setMapStyle);
266-
}
253+
onPressed: () async {
254+
_nightMode = !_nightMode;
255+
final String style =
256+
_nightMode ? await _getFileData('assets/night_mode.json') : '';
257+
setState(() {
258+
_mapStyle = style;
259+
});
267260
},
268261
);
269262
}
@@ -278,6 +271,7 @@ class MapUiBodyState extends State<MapUiBody> {
278271
cameraTargetBounds: _cameraTargetBounds,
279272
minMaxZoomPreference: _minMaxZoomPreference,
280273
mapType: _mapType,
274+
style: _mapStyle,
281275
rotateGesturesEnabled: _rotateGesturesEnabled,
282276
scrollGesturesEnabled: _scrollGesturesEnabled,
283277
tiltGesturesEnabled: _tiltGesturesEnabled,
@@ -352,5 +346,13 @@ class MapUiBodyState extends State<MapUiBody> {
352346
_controller = controller;
353347
_isMapCreated = true;
354348
});
349+
// Log any style errors to the console for debugging.
350+
if (kDebugMode) {
351+
_controller.getStyleError().then((String? error) {
352+
if (error != null) {
353+
debugPrint(error);
354+
}
355+
});
356+
}
355357
}
356358
}

packages/google_maps_flutter/google_maps_flutter/example/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ dependencies:
1919
# the parent directory to use the current plugin's version.
2020
path: ../
2121
google_maps_flutter_android: ^2.5.0
22-
google_maps_flutter_platform_interface: ^2.4.0
22+
google_maps_flutter_platform_interface: ^2.5.0
2323

2424
dev_dependencies:
2525
build_runner: ^2.1.10

packages/google_maps_flutter/google_maps_flutter/lib/src/controller.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,17 @@ class GoogleMapController {
190190
/// Also, refer [iOS](https://developers.google.com/maps/documentation/ios-sdk/style-reference)
191191
/// and [Android](https://developers.google.com/maps/documentation/android-sdk/style-reference)
192192
/// style reference for more information regarding the supported styles.
193+
@Deprecated('Use GoogleMap.style instead.')
193194
Future<void> setMapStyle(String? mapStyle) {
194195
return GoogleMapsFlutterPlatform.instance
195196
.setMapStyle(mapStyle, mapId: mapId);
196197
}
197198

199+
/// Returns the last style error, if any.
200+
Future<String?> getStyleError() {
201+
return GoogleMapsFlutterPlatform.instance.getStyleError(mapId: mapId);
202+
}
203+
198204
/// Return [LatLngBounds] defining the region that is visible in a map.
199205
Future<LatLngBounds> getVisibleRegion() {
200206
return GoogleMapsFlutterPlatform.instance.getVisibleRegion(mapId: mapId);

packages/google_maps_flutter/google_maps_flutter/lib/src/google_map.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class GoogleMap extends StatefulWidget {
9191
const GoogleMap({
9292
super.key,
9393
required this.initialCameraPosition,
94+
this.style,
9495
this.onMapCreated,
9596
this.gestureRecognizers = const <Factory<OneSequenceGestureRecognizer>>{},
9697
this.webGestureHandling,
@@ -136,6 +137,19 @@ class GoogleMap extends StatefulWidget {
136137
/// The initial position of the map's camera.
137138
final CameraPosition initialCameraPosition;
138139

140+
/// The style for the map.
141+
///
142+
/// Set to null to clear any previous custom styling.
143+
///
144+
/// If problems were detected with the [mapStyle], including un-parsable
145+
/// styling JSON, unrecognized feature type, unrecognized element type, or
146+
/// invalid styler keys, the style is left unchanged, and the error can be
147+
/// retrieved with [GoogleMapController.getStyleError].
148+
///
149+
/// The style string can be generated using the
150+
/// [map style tool](https://mapstyle.withgoogle.com/).
151+
final String? style;
152+
139153
/// True if the map should show a compass when rotated.
140154
final bool compassEnabled;
141155

@@ -556,5 +570,8 @@ MapConfiguration _configurationFromMapWidget(GoogleMap map) {
556570
trafficEnabled: map.trafficEnabled,
557571
buildingsEnabled: map.buildingsEnabled,
558572
cloudMapId: map.cloudMapId,
573+
// A null style in the widget means no style, which is expressed as '' in
574+
// the configuration to distinguish from no change (null).
575+
style: map.style ?? '',
559576
);
560577
}

packages/google_maps_flutter/google_maps_flutter/pubspec.yaml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ name: google_maps_flutter
22
description: A Flutter plugin for integrating Google Maps in iOS and Android applications.
33
repository: https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22
5-
version: 2.5.3
5+
version: 2.6.0
66

77
environment:
8-
sdk: ^3.1.0
9-
flutter: ">=3.13.0"
8+
sdk: ^3.3.0
9+
flutter: ">=3.19.0"
1010

1111
flutter:
1212
plugin:
@@ -21,10 +21,10 @@ flutter:
2121
dependencies:
2222
flutter:
2323
sdk: flutter
24-
google_maps_flutter_android: ^2.5.0
25-
google_maps_flutter_ios: ^2.3.0
26-
google_maps_flutter_platform_interface: ^2.4.0
27-
google_maps_flutter_web: ^0.5.2
24+
google_maps_flutter_android: ^2.7.0
25+
google_maps_flutter_ios: ^2.5.0
26+
google_maps_flutter_platform_interface: ^2.5.0
27+
google_maps_flutter_web: ^0.5.6
2828

2929
dev_dependencies:
3030
flutter_test:

packages/google_maps_flutter/google_maps_flutter/test/google_map_test.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,4 +551,32 @@ void main() {
551551

552552
expect(map.mapConfiguration.buildingsEnabled, true);
553553
});
554+
555+
testWidgets('Can update style', (WidgetTester tester) async {
556+
const String initialStyle = '[]';
557+
await tester.pumpWidget(
558+
const Directionality(
559+
textDirection: TextDirection.ltr,
560+
child: GoogleMap(
561+
initialCameraPosition: CameraPosition(target: LatLng(10.0, 15.0)),
562+
style: initialStyle,
563+
),
564+
),
565+
);
566+
567+
final PlatformMapStateRecorder map = platform.lastCreatedMap;
568+
569+
expect(map.mapConfiguration.style, initialStyle);
570+
571+
await tester.pumpWidget(
572+
const Directionality(
573+
textDirection: TextDirection.ltr,
574+
child: GoogleMap(
575+
initialCameraPosition: CameraPosition(target: LatLng(10.0, 15.0)),
576+
),
577+
),
578+
);
579+
580+
expect(map.mapConfiguration.style, '');
581+
});
554582
}

0 commit comments

Comments
 (0)