Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Support Hybrid Composition through the GoogleMaps Widget #4082

Merged
merged 17 commits into from
Oct 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 2.1.0

* Add iOS unit and UI integration test targets.
* Provide access to Hybrid Composition on Android through the `GoogleMap` widget.

## 2.0.11

* Add additional marker drag events.
Expand Down
12 changes: 12 additions & 0 deletions packages/google_maps_flutter/google_maps_flutter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ This means that app will only be available for users that run Android SDK 20 or
android:value="YOUR KEY HERE"/>
```

#### Hybrid Composition

To use [Hybrid Composition](https://flutter.dev/docs/development/platform-integration/platform-views)
to render the `GoogleMap` widget on Android, set `AndroidGoogleMapsFlutter.useAndroidViewSurface` to
true.

```dart
if (defaultTargetPlatform == TargetPlatform.android) {
AndroidGoogleMapsFlutter.useAndroidViewSurface = true;
}
```

### iOS

This plugin requires iOS 9.0 or higher. To set up, specify your API key in the application delegate `ios/Runner/AppDelegate.m`:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

// ignore_for_file: public_member_api_docs

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:google_maps_flutter_example/lite_mode.dart';
import 'animate_camera.dart';
import 'map_click.dart';
Expand Down Expand Up @@ -66,5 +69,8 @@ class MapsDemo extends StatelessWidget {
}

void main() {
if (defaultTargetPlatform == TargetPlatform.android) {
AndroidGoogleMapsFlutter.useAndroidViewSurface = true;
}
runApp(MaterialApp(home: MapsDemo()));
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,44 @@ class UnknownMapObjectIdError extends Error {
}
}

/// Android specific settings for [GoogleMap].
class AndroidGoogleMapsFlutter {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect this to be a MethodChannelGoogleMapsFlutter subclass. I guess we can add that later without it being a breaking change though, and doing it now would have registration complexities since we don't have dartPluginClass support for mobile on stable yet.

/// Whether to render [GoogleMap] with a [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.
///
/// Defaults to false.
static bool get useAndroidViewSurface {
final GoogleMapsFlutterPlatform platform =
GoogleMapsFlutterPlatform.instance;
if (platform is MethodChannelGoogleMapsFlutter) {
return platform.useAndroidViewSurface;
}
return false;
}

/// Set whether to render [GoogleMap] with a [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.
///
/// Defaults to false.
static set useAndroidViewSurface(bool useAndroidViewSurface) {
final GoogleMapsFlutterPlatform platform =
GoogleMapsFlutterPlatform.instance;
if (platform is MethodChannelGoogleMapsFlutter) {
platform.useAndroidViewSurface = useAndroidViewSurface;
}
}
}

/// 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.
Expand All @@ -61,6 +99,7 @@ class GoogleMap extends StatefulWidget {
this.tiltGesturesEnabled = true,
this.myLocationEnabled = false,
this.myLocationButtonEnabled = true,
this.layoutDirection,

/// If no padding is specified default padding will be 0.
this.padding = const EdgeInsets.all(0),
Expand Down Expand Up @@ -100,6 +139,12 @@ class GoogleMap extends StatefulWidget {
/// Type of map tiles to be rendered.
final MapType mapType;

/// The layout direction to use for the embedded view.
///
/// If this is null, the ambient [Directionality] is used instead. If there is
/// no ambient [Directionality], [TextDirection.ltr] is used.
final TextDirection? layoutDirection;

/// Preferred bounds for the camera zoom level.
///
/// Actual bounds depend on map data and device.
Expand Down Expand Up @@ -250,9 +295,12 @@ class _GoogleMapState extends State<GoogleMap> {

@override
Widget build(BuildContext context) {
return GoogleMapsFlutterPlatform.instance.buildView(
return GoogleMapsFlutterPlatform.instance.buildViewWithTextDirection(
_mapId,
onPlatformViewCreated,
textDirection: widget.layoutDirection ??
Directionality.maybeOf(context) ??
Copy link
Contributor Author

@bparrishMines bparrishMines Aug 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may return null if there is no Directionality ancestor. This was the case with one of the tests, so I also added a default TextDirection.ltr.

TextDirection.ltr,
initialCameraPosition: widget.initialCameraPosition,
markers: widget.markers,
polygons: widget.polygons,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: google_maps_flutter
description: A Flutter plugin for integrating Google Maps in iOS and Android applications.
repository: https://github.com/flutter/plugins/tree/master/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.0.11
version: 2.1.0

environment:
sdk: ">=2.14.0 <3.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:flutter/services.dart';
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 'fake_maps_controllers.dart';

Expand Down Expand Up @@ -604,17 +605,21 @@ void main() {
},
);

// 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);
// });
testWidgets('Use PlatformViewLink on Android', (WidgetTester tester) async {
final MethodChannelGoogleMapsFlutter platform =
GoogleMapsFlutterPlatform.instance as MethodChannelGoogleMapsFlutter;
platform.useAndroidViewSurface = true;

await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
child: GoogleMap(
initialCameraPosition: CameraPosition(target: LatLng(10.0, 15.0)),
),
),
);

expect(find.byType(PlatformViewLink), findsOneWidget);
platform.useAndroidViewSurface = false;
});
}