Skip to content

Commit 31db502

Browse files
authored
Configurable android view hosting mode (#391)
* Expose a way to configure android platform view hosting mode * Add a changelog entry * Downgrade meta to 1.10.0 * Remove test code * Downgrade meta to 1.9.1 * Remove accidentally commited code * fix failing test
1 parent d48fbc5 commit 31db502

File tree

8 files changed

+118
-25
lines changed

8 files changed

+118
-25
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
* Add an example representing a traffic route with color based on traffic volumes using LineLayer and Expression.
44
* [Android] Fix MapOptions incorrect index access at map creation, leading to map not being created(blank view).
5+
* [Android] Use hybrid composition(HC) as the default platform view hosting mode on Android.
6+
* [Android] Add experimental `androidHostingMode` contructor parameter to `MapWidget`. Use this to change the way platform MapView is being hosted by Flutter on Android. This changes the way map view is composited with Flutter UI, read more on this in [Android Platform Views](https://github.com/flutter/flutter/wiki/Android-Platform-Views) guide from the Flutter team.
57
* [iOS] `MapboxMap`: `isGestureInProgress()`, `isUserAnimationInProgress()`, `setConstrainMode()`, `setNorthOrientation()`, `setViewportMode()` and `reduceMemoryUse()` are now available on iOS.
68
* Bump platform Maps SDK dependencies to 11.2.0-beta.1.
79

example/integration_test/map_interface_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ void main() {
5454
await tester.pumpAndSettle();
5555
final mapboxMap = await mapFuture;
5656
var size = await mapboxMap.getSize();
57-
expect(size.width, tester.binding.renderView.size.width);
58-
expect(size.height, tester.binding.renderView.size.height);
57+
expect(size.width, closeTo(tester.binding.renderView.size.width, 1));
58+
expect(size.height, closeTo(tester.binding.renderView.size.height, 1));
5959
});
6060
}
6161

example/pubspec.lock

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ packages:
103103
source: sdk
104104
version: "0.0.0"
105105
flutter_driver:
106-
dependency: "direct dev"
106+
dependency: transitive
107107
description: flutter
108108
source: sdk
109109
version: "0.0.0"
@@ -124,10 +124,10 @@ packages:
124124
dependency: "direct main"
125125
description:
126126
name: font_awesome_flutter
127-
sha256: "52671aea66da73b58d42ec6d0912b727a42248dd9a7c76d6c20f275783c48c08"
127+
sha256: "275ff26905134bcb59417cf60ad979136f1f8257f2f449914b2c3e05bbb4cd6f"
128128
url: "https://pub.dev"
129129
source: hosted
130-
version: "10.6.0"
130+
version: "10.7.0"
131131
fuchsia_remote_debug_protocol:
132132
dependency: transitive
133133
description: flutter
@@ -314,10 +314,10 @@ packages:
314314
dependency: transitive
315315
description:
316316
name: sweepline_intersections
317-
sha256: "924fce1b02b9783fae5ca33ba4f2cc33743b0422b8b829fac60bcd3717a69afb"
317+
sha256: a665c707200a4f07140a4029b41a7c4883beb3f04322cd8e08ebf650f69e1176
318318
url: "https://pub.dev"
319319
source: hosted
320-
version: "0.0.3+2"
320+
version: "0.0.4"
321321
sync_http:
322322
dependency: transitive
323323
description:
@@ -346,26 +346,26 @@ packages:
346346
dependency: "direct dev"
347347
description:
348348
name: turf
349-
sha256: "2be48cc7ed7e9acccaeee18e06d1ce183f3f7eee7abc0622371880951d41a0d6"
349+
sha256: e5774828b5a21b789946041bd3b0066fb6dc880449264eaeab605e3c5358c350
350350
url: "https://pub.dev"
351351
source: hosted
352-
version: "0.0.8"
352+
version: "0.0.9"
353353
turf_equality:
354354
dependency: transitive
355355
description:
356356
name: turf_equality
357-
sha256: "2ae3b117afd5fb134412a245a883589cae80d9d9472c587f754a0c34f82fa1b9"
357+
sha256: "61deee4a915a2c3d249be4ee6d6180b2d744e5a6298e1d668213d529766c6a21"
358358
url: "https://pub.dev"
359359
source: hosted
360-
version: "0.0.2"
360+
version: "0.0.3"
361361
turf_pip:
362362
dependency: transitive
363363
description:
364364
name: turf_pip
365-
sha256: "2b33d14ad979e4c33a4f01949b62510356d28037062bd45b60752e4dec9e7dd1"
365+
sha256: ba4fd414baffd5d7b30880658ad6db82461c49ec023f8ffd0c23d398ad8b14be
366366
url: "https://pub.dev"
367367
source: hosted
368-
version: "0.0.1+1"
368+
version: "0.0.2"
369369
typed_data:
370370
dependency: transitive
371371
description:

example/pubspec.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ dev_dependencies:
2929
sdk: flutter
3030
integration_test:
3131
sdk: flutter
32-
flutter_driver:
33-
sdk: flutter
3432
turf: ^0.0.7
3533

3634
# For information on the generic Dart part of this file, see the

lib/mapbox_maps_flutter.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import 'package:enum_to_string/enum_to_string.dart';
88
import 'package:flutter/foundation.dart';
99
import 'package:flutter/gestures.dart';
1010
import 'package:flutter/material.dart';
11+
import 'package:flutter/rendering.dart';
1112
import 'package:flutter/services.dart';
13+
import 'package:meta/meta.dart';
1214

1315
import 'src/proxy_binary_messenger.dart' show ProxyBinaryMessenger;
1416

lib/src/map_widget.dart

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
11
part of mapbox_maps_flutter;
22

3+
/// A mode for platform MapView to be hosted in Flutter on Android platform.
4+
///
5+
/// As per https://github.com/flutter/flutter/wiki/Android-Platform-Views#selecting-a-mode
6+
@experimental
7+
enum AndroidPlatformViewHostingMode {
8+
/// Texture Layer Hybrid Composition with fallback to Virtual Display,
9+
/// when the current SDK version is <23 or [MapWidget.textureView] is `false`.
10+
///
11+
/// https://github.com/flutter/flutter/wiki/Texture-Layer-Hybrid-Composition
12+
TLHC_VD,
13+
14+
/// Use Texture Layer Hybrid Composition hosting mode with fallback to Hybrid Composition,
15+
/// when the current SDK version is <23 or [MapWidget.textureView] is `false`.
16+
///
17+
/// https://github.com/flutter/flutter/wiki/Texture-Layer-Hybrid-Composition
18+
TLHC_HC,
19+
20+
/// Always use Hybrid Composition hosting mode.
21+
///
22+
/// https://github.com/flutter/flutter/wiki/Hybrid-Composition
23+
HC,
24+
25+
/// Always use Virtual Display hosting mode.
26+
///
27+
/// https://github.com/flutter/flutter/wiki/Virtual-Display
28+
VD,
29+
}
30+
331
/// A MapWidget provides an embeddable map interface.
432
/// You use this class to display map information and to manipulate the map contents from your application.
533
/// You can center the map on a given coordinate, specify the size of the area you want to display,
@@ -18,6 +46,7 @@ class MapWidget extends StatefulWidget {
1846
// FIXME Flutter 3.x has memory leak on Android using in SurfaceView mode, see https://github.com/flutter/flutter/issues/118384
1947
// As a workaround default is true.
2048
this.textureView = true,
49+
this.androidHostingMode = AndroidPlatformViewHostingMode.HC,
2150
this.styleUri = MapboxStyles.STANDARD,
2251
this.gestureRecognizers,
2352
this.onMapCreated,
@@ -91,6 +120,11 @@ class MapWidget extends StatefulWidget {
91120
/// As a workaround default is true.
92121
final bool? textureView;
93122

123+
/// Controls the way the underlaying MapView is being hosted by Flutter on Android.
124+
/// This setting has no effect on iOS.
125+
@experimental
126+
final AndroidPlatformViewHostingMode androidHostingMode;
127+
94128
/// The styleUri will applied for the MapWidget in the onStart lifecycle event if no style is set. Default is [Style.MAPBOX_STREETS].
95129
final String styleUri;
96130

@@ -186,7 +220,7 @@ class _MapWidgetState extends State<MapWidget> {
186220
'mapboxPluginVersion': '1.0.0-beta.2'
187221
};
188222

189-
return _mapboxMapsPlatform.buildView(
223+
return _mapboxMapsPlatform.buildView(widget.androidHostingMode,
190224
creationParams, onPlatformViewCreated, widget.gestureRecognizers);
191225
}
192226

lib/src/mapbox_maps_platform.dart

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,19 +111,56 @@ class _MapboxMapsPlatform {
111111
}
112112

113113
Widget buildView(
114+
AndroidPlatformViewHostingMode androidHostingMode,
114115
Map<String, dynamic> creationParams,
115116
OnPlatformViewCreatedCallback onPlatformViewCreated,
116117
Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers) {
117118
creationParams['channelSuffix'] = _channelSuffix;
118119

119120
if (defaultTargetPlatform == TargetPlatform.android) {
120-
return AndroidView(
121-
viewType: 'plugins.flutter.io/mapbox_maps',
122-
onPlatformViewCreated: onPlatformViewCreated,
123-
gestureRecognizers: gestureRecognizers,
124-
creationParams: creationParams,
125-
creationParamsCodec: const StandardMessageCodec(),
126-
);
121+
122+
switch (androidHostingMode) {
123+
case AndroidPlatformViewHostingMode.TLHC_VD:
124+
case AndroidPlatformViewHostingMode.TLHC_HC:
125+
case AndroidPlatformViewHostingMode.HC:
126+
return PlatformViewLink(
127+
viewType: "plugins.flutter.io/mapbox_maps",
128+
surfaceFactory: (context, controller) {
129+
return AndroidViewSurface(
130+
controller: controller as AndroidViewController,
131+
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
132+
gestureRecognizers: gestureRecognizers ?? Set());
133+
},
134+
onCreatePlatformView: (params) {
135+
final AndroidViewController controller =
136+
_androidViewControllerFactoryForMode(androidHostingMode)(
137+
id: params.id,
138+
viewType: 'plugins.flutter.io/mapbox_maps',
139+
layoutDirection: TextDirection.ltr,
140+
creationParams: creationParams,
141+
creationParamsCodec: const StandardMessageCodec(),
142+
onFocus: () => params.onFocusChanged(true),
143+
);
144+
controller.addOnPlatformViewCreatedListener(
145+
params.onPlatformViewCreated,
146+
);
147+
controller.addOnPlatformViewCreatedListener(
148+
onPlatformViewCreated,
149+
);
150+
151+
controller.create();
152+
return controller;
153+
},
154+
);
155+
case AndroidPlatformViewHostingMode.VD:
156+
return AndroidView(
157+
viewType: 'plugins.flutter.io/mapbox_maps',
158+
onPlatformViewCreated: onPlatformViewCreated,
159+
gestureRecognizers: gestureRecognizers,
160+
creationParams: creationParams,
161+
creationParamsCodec: const StandardMessageCodec(),
162+
);
163+
}
127164
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
128165
return UiKitView(
129166
viewType: 'plugins.flutter.io/mapbox_maps',
@@ -137,6 +174,27 @@ class _MapboxMapsPlatform {
137174
'$defaultTargetPlatform is not yet supported by the maps plugin');
138175
}
139176

177+
AndroidViewController Function(
178+
{required int id,
179+
required String viewType,
180+
required TextDirection layoutDirection,
181+
dynamic creationParams,
182+
MessageCodec<dynamic>? creationParamsCodec,
183+
VoidCallback? onFocus})
184+
_androidViewControllerFactoryForMode(
185+
AndroidPlatformViewHostingMode hostingMode) {
186+
switch (hostingMode) {
187+
case AndroidPlatformViewHostingMode.TLHC_VD:
188+
return PlatformViewsService.initAndroidView;
189+
case AndroidPlatformViewHostingMode.TLHC_HC:
190+
return PlatformViewsService.initSurfaceAndroidView;
191+
case AndroidPlatformViewHostingMode.HC:
192+
return PlatformViewsService.initExpensiveAndroidView;
193+
case AndroidPlatformViewHostingMode.VD:
194+
throw "Unexpected hostring mode(VD) when selecting an android view controller";
195+
}
196+
}
197+
140198
void dispose() {
141199
_suffixesRegistry.releaseSuffix(_channelSuffix);
142200
_channel.setMethodCallHandler(null);

pubspec.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@ dependencies:
1414
flutter_plugin_android_lifecycle: ^2.0.5
1515
turf: ^0.0.8
1616
typed_data: ^1.3.0
17+
meta: ^1.9.1
1718

1819
dev_dependencies:
1920
integration_test:
2021
sdk: flutter
21-
flutter_driver:
22-
sdk: flutter
2322
flutter_test:
2423
sdk: flutter
2524
test: ^1.19.0

0 commit comments

Comments
 (0)