Support Hybrid Composition on Android (#4017)
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 2b754af..d1ec87a 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
@@ -587,4 +587,34 @@
expect(platformGoogleMap.buildingsEnabled, true);
});
+
+ testWidgets(
+ 'Default Android widget is AndroidView',
+ (WidgetTester tester) async {
+ await tester.pumpWidget(
+ const Directionality(
+ textDirection: TextDirection.ltr,
+ child: GoogleMap(
+ initialCameraPosition: CameraPosition(target: LatLng(10.0, 15.0)),
+ ),
+ ),
+ );
+
+ expect(find.byType(AndroidView), findsOneWidget);
+ },
+ );
+
+ // TODO(bparrishMines): Uncomment once https://github.com/flutter/plugins/pull/4017 has landed.
+ // testWidgets('Use AndroidViewSurface on Android', (WidgetTester tester) async {
+ // await tester.pumpWidget(
+ // const Directionality(
+ // textDirection: TextDirection.ltr,
+ // child: GoogleMap(
+ // initialCameraPosition: CameraPosition(target: LatLng(10.0, 15.0)),
+ // ),
+ // ),
+ // );
+ //
+ // expect(find.byType(AndroidViewSurface), findsOneWidget);
+ // });
}
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 b6603d6..2dc533f 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,8 @@
+## 2.1.0
+
+* Add support for Hybrid Composition when building the Google Maps widget on Android. Set
+ `MethodChannelGoogleMapsFlutter.useAndroidViewSurface` to `true` to build with Hybrid Composition.
+
## 2.0.4
* Preserve the `TileProvider` when copying `TileOverlay`, fixing a
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/google_maps_flutter_platform_interface.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/google_maps_flutter_platform_interface.dart
index 650a839..3007000 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/google_maps_flutter_platform_interface.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/google_maps_flutter_platform_interface.dart
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+export 'src/method_channel/method_channel_google_maps_flutter.dart'
+ show MethodChannelGoogleMapsFlutter;
export 'src/platform_interface/google_maps_flutter_platform.dart';
export 'src/types/types.dart';
export 'src/events/map_event.dart';
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/method_channel/method_channel_google_maps_flutter.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/method_channel/method_channel_google_maps_flutter.dart
index 49029cc..41aedc7 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/method_channel/method_channel_google_maps_flutter.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/method_channel/method_channel_google_maps_flutter.dart
@@ -8,6 +8,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
+import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
import 'package:stream_transform/stream_transform.dart';
@@ -441,6 +442,98 @@
return channel(mapId).invokeMethod<Uint8List>('map#takeSnapshot');
}
+ /// Set [GoogleMapsFlutterPlatform] to use [AndroidViewSurface] to build the Google Maps widget.
+ ///
+ /// This implementation uses hybrid composition to render the Google Maps
+ /// Widget on Android. This comes at the cost of some performance on Android
+ /// versions below 10. See
+ /// https://flutter.dev/docs/development/platform-integration/platform-views#performance for more
+ /// information.
+ ///
+ /// If set to true, the google map widget should be built with
+ /// [buildViewWithTextDirection] instead of [buildView].
+ ///
+ /// Defaults to false.
+ bool useAndroidViewSurface = false;
+
+ /// Returns a widget displaying the map view.
+ ///
+ /// This method includes a parameter for platforms that require a text
+ /// direction. For example, this should be used when using hybrid composition
+ /// on Android.
+ Widget buildViewWithTextDirection(
+ int creationId,
+ PlatformViewCreatedCallback onPlatformViewCreated, {
+ required CameraPosition initialCameraPosition,
+ required TextDirection textDirection,
+ Set<Marker> markers = const <Marker>{},
+ Set<Polygon> polygons = const <Polygon>{},
+ Set<Polyline> polylines = const <Polyline>{},
+ Set<Circle> circles = const <Circle>{},
+ Set<TileOverlay> tileOverlays = const <TileOverlay>{},
+ Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers,
+ Map<String, dynamic> mapOptions = const <String, dynamic>{},
+ }) {
+ if (defaultTargetPlatform == TargetPlatform.android &&
+ useAndroidViewSurface) {
+ final Map<String, dynamic> creationParams = <String, dynamic>{
+ 'initialCameraPosition': initialCameraPosition.toMap(),
+ 'options': mapOptions,
+ 'markersToAdd': serializeMarkerSet(markers),
+ 'polygonsToAdd': serializePolygonSet(polygons),
+ 'polylinesToAdd': serializePolylineSet(polylines),
+ 'circlesToAdd': serializeCircleSet(circles),
+ 'tileOverlaysToAdd': serializeTileOverlaySet(tileOverlays),
+ };
+ return PlatformViewLink(
+ viewType: 'plugins.flutter.io/google_maps',
+ surfaceFactory: (
+ BuildContext context,
+ PlatformViewController controller,
+ ) {
+ return AndroidViewSurface(
+ controller: controller as AndroidViewController,
+ gestureRecognizers: gestureRecognizers ??
+ const <Factory<OneSequenceGestureRecognizer>>{},
+ hitTestBehavior: PlatformViewHitTestBehavior.opaque,
+ );
+ },
+ onCreatePlatformView: (PlatformViewCreationParams params) {
+ final SurfaceAndroidViewController controller =
+ PlatformViewsService.initSurfaceAndroidView(
+ id: params.id,
+ viewType: 'plugins.flutter.io/google_maps',
+ layoutDirection: textDirection,
+ creationParams: creationParams,
+ creationParamsCodec: const StandardMessageCodec(),
+ onFocus: () => params.onFocusChanged(true),
+ );
+ controller.addOnPlatformViewCreatedListener(
+ params.onPlatformViewCreated,
+ );
+ controller.addOnPlatformViewCreatedListener(
+ onPlatformViewCreated,
+ );
+
+ controller.create();
+ return controller;
+ },
+ );
+ }
+ return buildView(
+ creationId,
+ onPlatformViewCreated,
+ initialCameraPosition: initialCameraPosition,
+ markers: markers,
+ polygons: polygons,
+ polylines: polylines,
+ circles: circles,
+ tileOverlays: tileOverlays,
+ gestureRecognizers: gestureRecognizers,
+ mapOptions: mapOptions,
+ );
+ }
+
@override
Widget buildView(
int creationId,
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 5b278a8..1ea425e 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
@@ -4,7 +4,7 @@
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22
# 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: 2.0.4
+version: 2.1.0
environment:
sdk: '>=2.12.0 <3.0.0'