diff --git a/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md index 8ad0c02d3f77..5d62a5179fd4 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.29 + +* Pass a constant `_web_only_mapCreationId` to `platform.buildView`, so web can return a cached widget DOM when flutter attempts to repaint there. +* Modify some examples slightly so they're more web-friendly. + ## 0.5.28+2 * Move test introduced in #2449 to its right location. diff --git a/packages/google_maps_flutter/google_maps_flutter/example/lib/marker_icons.dart b/packages/google_maps_flutter/google_maps_flutter/example/lib/marker_icons.dart index e0fcc427c1d6..b62d898c3a3b 100644 --- a/packages/google_maps_flutter/google_maps_flutter/example/lib/marker_icons.dart +++ b/packages/google_maps_flutter/google_maps_flutter/example/lib/marker_icons.dart @@ -73,7 +73,7 @@ class MarkerIconsBodyState extends State { Future _createMarkerImageFromAsset(BuildContext context) async { if (_markerIcon == null) { final ImageConfiguration imageConfiguration = - createLocalImageConfiguration(context); + createLocalImageConfiguration(context, size: Size.square(48)); BitmapDescriptor.fromAssetImage( imageConfiguration, 'assets/red_square.png') .then(_updateBitmap); diff --git a/packages/google_maps_flutter/google_maps_flutter/example/lib/place_polyline.dart b/packages/google_maps_flutter/google_maps_flutter/example/lib/place_polyline.dart index 0c9da634faa7..35ffd33a53c2 100644 --- a/packages/google_maps_flutter/google_maps_flutter/example/lib/place_polyline.dart +++ b/packages/google_maps_flutter/google_maps_flutter/example/lib/place_polyline.dart @@ -4,8 +4,7 @@ // ignore_for_file: public_member_api_docs -import 'dart:io' show Platform; - +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; @@ -202,7 +201,9 @@ class PlacePolylineBodyState extends State { @override Widget build(BuildContext context) { - final bool iOSorNotSelected = Platform.isIOS || (selectedPolyline == null); + final bool iOSorNotSelected = + (!kIsWeb && defaultTargetPlatform == TargetPlatform.iOS) || + (selectedPolyline == null); return Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, 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 a45a1c8e3fe4..5cf3db120ccd 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 @@ -10,6 +10,12 @@ part of google_maps_flutter; /// map is created. typedef void MapCreatedCallback(GoogleMapController controller); +// This counter is used to provide a stable "constant" initialization id +// to the buildView function, so the web implementation can use it as a +// cache key. This needs to be provided from the outside, because web +// views seem to re-render much more often that mobile platform views. +int _webOnlyMapId = 0; + /// A widget which displays a map with data obtained from the Google Maps service. class GoogleMap extends StatefulWidget { /// Creates a widget displaying data from Google Maps services. @@ -205,6 +211,8 @@ class GoogleMap extends StatefulWidget { } class _GoogleMapState extends State { + final _webOnlyMapCreationId = _webOnlyMapId++; + final Completer _controller = Completer(); @@ -223,7 +231,9 @@ class _GoogleMapState extends State { 'polygonsToAdd': serializePolygonSet(widget.polygons), 'polylinesToAdd': serializePolylineSet(widget.polylines), 'circlesToAdd': serializeCircleSet(widget.circles), + '_webOnlyMapCreationId': _webOnlyMapCreationId, }; + return _googleMapsFlutterPlatform.buildView( creationParams, widget.gestureRecognizers, diff --git a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml index 5e3cf226f03d..120600a9823c 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.28+2 +version: 0.5.29 dependencies: flutter: @@ -19,6 +19,8 @@ dev_dependencies: sdk: flutter test: ^1.6.0 pedantic: ^1.8.0 + plugin_platform_interface: ^1.0.2 + mockito: ^4.1.1 flutter: plugin: diff --git a/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart b/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart new file mode 100644 index 000000000000..7861c86e9709 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter/test/map_creation_test.dart @@ -0,0 +1,64 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; +import 'package:mockito/mockito.dart'; + +class MockGoogleMapsFlutterPlatform extends Mock + with MockPlatformInterfaceMixin + implements GoogleMapsFlutterPlatform {} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + final platform = MockGoogleMapsFlutterPlatform(); + + setUp(() { + // Use a mock platform so we never need to hit the MethodChannel code. + GoogleMapsFlutterPlatform.instance = platform; + when(platform.buildView(any, any, any)).thenReturn(Container()); + }); + + testWidgets('_webOnlyMapCreationId increments with each GoogleMap widget', ( + WidgetTester tester, + ) async { + // Inject two map widgets... + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: Column( + children: const [ + GoogleMap( + initialCameraPosition: CameraPosition( + target: LatLng(43.362, -5.849), + ), + ), + GoogleMap( + initialCameraPosition: CameraPosition( + target: LatLng(47.649, -122.350), + ), + ), + ], + ), + ), + ); + + // Verify that each one was created with a different _webOnlyMapCreationId. + verifyInOrder([ + platform.buildView( + argThat(containsPair('_webOnlyMapCreationId', 0)), + any, + any, + ), + platform.buildView( + argThat(containsPair('_webOnlyMapCreationId', 1)), + any, + any, + ), + ]); + }); +} diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md index eca5c914a603..47cb8ecc15ad 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.3 + +* Pass icon width/height if present on `fromAssetImage` BitmapDescriptors (web only) + ## 1.0.2 * Update lower bound of dart dependency to 2.1.0. diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart index 40581b43e065..a6fdcc1b7e33 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart @@ -9,6 +9,8 @@ import 'package:flutter/material.dart' show ImageConfiguration, AssetImage, AssetBundleImageKey; import 'package:flutter/services.dart' show AssetBundle; +import 'package:flutter/foundation.dart' show kIsWeb; + /// Defines a bitmap image. For a marker, this class can be used to set the /// image of the marker icon. For a ground overlay, it can be used to set the /// image to place on the surface of the earth. @@ -100,6 +102,11 @@ class BitmapDescriptor { 'fromAssetImage', assetBundleImageKey.name, assetBundleImageKey.scale, + if (kIsWeb && configuration?.size != null) + [ + configuration.size.width, + configuration.size.height, + ], ]); } diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml index b28b7f47652d..f062b25c79ea 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml @@ -3,7 +3,7 @@ description: A common platform interface for the google_maps_flutter plugin. homepage: https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 1.0.2 +version: 1.0.3 dependencies: flutter: @@ -19,5 +19,5 @@ dev_dependencies: pedantic: ^1.8.0 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.3.0 <3.0.0" flutter: ">=1.9.1+hotfix.4 <2.0.0"