[web] Pass creation params to the platform view factory (#128146)
This concludes step 1 of the `HtmlElementView` improvements. It's now possible to pass creation params to platform view factories directly from `HtmlElementView`. Here's a sample app using a single factory to render platform views in different colors: <details> <summary>Code sample</summary> ```dart import 'dart:js_interop'; import 'dart:ui_web' as ui_web; import 'package:flutter/material.dart'; import 'package:web/web.dart' as web; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Platform View Demo', home: Scaffold( appBar: AppBar( title: Text('Platform View Demo'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ BoxWrapper('red'), BoxWrapper(null), BoxWrapper('blue'), ], ), ), ), ); } } bool isRegistered = false; class BoxWrapper extends StatelessWidget { const BoxWrapper(this.cssColor); final String? cssColor; void register() { if (isRegistered) return; isRegistered = true; ui_web.platformViewRegistry.registerViewFactory('my-platform-view', ( id, { Object? params, }) { params as String?; final element = web.document.createElement('div'.toJS) as web.HTMLElement; element.textContent = 'Platform View'.toJS; element.style ..lineHeight = '100px'.toJS ..fontSize = '24px'.toJS ..backgroundColor = (params ?? 'pink').toJS ..textAlign = 'center'.toJS; return element; }); } @override Widget build(BuildContext context) { register(); return SizedBox( width: 200, height: 100, child: Card( child: HtmlElementView( viewType: 'my-platform-view', creationParams: cssColor, ), ), ); } } ``` </details>  Depends on https://github.com/flutter/engine/pull/42255 Part of https://github.com/flutter/flutter/issues/127030
This commit is contained in:
parent
3246808cd2
commit
b0188cd182
@ -345,6 +345,7 @@ class HtmlElementView extends StatelessWidget {
|
||||
super.key,
|
||||
required this.viewType,
|
||||
this.onPlatformViewCreated,
|
||||
this.creationParams,
|
||||
}) : assert(kIsWeb, 'HtmlElementView is only available on Flutter Web.');
|
||||
|
||||
/// The unique identifier for the HTML view type to be embedded by this widget.
|
||||
@ -357,6 +358,9 @@ class HtmlElementView extends StatelessWidget {
|
||||
/// May be null.
|
||||
final PlatformViewCreatedCallback? onPlatformViewCreated;
|
||||
|
||||
/// Passed as the 2nd argument (i.e. `params`) of the registered view factory.
|
||||
final Object? creationParams;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PlatformViewLink(
|
||||
@ -374,7 +378,11 @@ class HtmlElementView extends StatelessWidget {
|
||||
|
||||
/// Creates the controller and kicks off its initialization.
|
||||
_HtmlElementViewController _createHtmlElementView(PlatformViewCreationParams params) {
|
||||
final _HtmlElementViewController controller = _HtmlElementViewController(params.id, viewType);
|
||||
final _HtmlElementViewController controller = _HtmlElementViewController(
|
||||
params.id,
|
||||
viewType,
|
||||
creationParams,
|
||||
);
|
||||
controller._initialize().then((_) {
|
||||
params.onPlatformViewCreated(params.id);
|
||||
onPlatformViewCreated?.call(params.id);
|
||||
@ -387,6 +395,7 @@ class _HtmlElementViewController extends PlatformViewController {
|
||||
_HtmlElementViewController(
|
||||
this.viewId,
|
||||
this.viewType,
|
||||
this.creationParams,
|
||||
);
|
||||
|
||||
@override
|
||||
@ -397,12 +406,15 @@ class _HtmlElementViewController extends PlatformViewController {
|
||||
/// A PlatformViewFactory for this type must have been registered.
|
||||
final String viewType;
|
||||
|
||||
final dynamic creationParams;
|
||||
|
||||
bool _initialized = false;
|
||||
|
||||
Future<void> _initialize() async {
|
||||
final Map<String, dynamic> args = <String, dynamic>{
|
||||
'id': viewId,
|
||||
'viewType': viewType,
|
||||
'params': creationParams,
|
||||
};
|
||||
await SystemChannels.platform_views.invokeMethod<void>('create', args);
|
||||
_initialized = true;
|
||||
|
@ -503,6 +503,7 @@ class FakeHtmlPlatformViewsController {
|
||||
final Map<dynamic, dynamic> args = call.arguments as Map<dynamic, dynamic>;
|
||||
final int id = args['id'] as int;
|
||||
final String viewType = args['viewType'] as String;
|
||||
final Object? params = args['params'];
|
||||
|
||||
if (_views.containsKey(id)) {
|
||||
throw PlatformException(
|
||||
@ -522,7 +523,7 @@ class FakeHtmlPlatformViewsController {
|
||||
await createCompleter!.future;
|
||||
}
|
||||
|
||||
_views[id] = FakeHtmlPlatformView(id, viewType);
|
||||
_views[id] = FakeHtmlPlatformView(id, viewType, params);
|
||||
return Future<int?>.sync(() => null);
|
||||
}
|
||||
|
||||
@ -658,10 +659,11 @@ class FakeUiKitView {
|
||||
|
||||
@immutable
|
||||
class FakeHtmlPlatformView {
|
||||
const FakeHtmlPlatformView(this.id, this.type);
|
||||
const FakeHtmlPlatformView(this.id, this.type, [this.creationParams]);
|
||||
|
||||
final int id;
|
||||
final String type;
|
||||
final Object? creationParams;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
@ -670,14 +672,15 @@ class FakeHtmlPlatformView {
|
||||
}
|
||||
return other is FakeHtmlPlatformView
|
||||
&& other.id == id
|
||||
&& other.type == type;
|
||||
&& other.type == type
|
||||
&& other.creationParams == creationParams;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, type);
|
||||
int get hashCode => Object.hash(id, type, creationParams);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'FakeHtmlPlatformView(id: $id, type: $type)';
|
||||
return 'FakeHtmlPlatformView(id: $id, type: $type, params: $creationParams)';
|
||||
}
|
||||
}
|
||||
|
@ -73,6 +73,42 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Create HTML view with creation params', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
final FakeHtmlPlatformViewsController viewsController = FakeHtmlPlatformViewsController();
|
||||
viewsController.registerViewType('webview');
|
||||
await tester.pumpWidget(
|
||||
const Column(
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
width: 200.0,
|
||||
height: 100.0,
|
||||
child: HtmlElementView(
|
||||
viewType: 'webview',
|
||||
creationParams: 'foobar',
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 200.0,
|
||||
height: 100.0,
|
||||
child: HtmlElementView(
|
||||
viewType: 'webview',
|
||||
creationParams: 123,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
expect(
|
||||
viewsController.views,
|
||||
unorderedEquals(<FakeHtmlPlatformView>[
|
||||
FakeHtmlPlatformView(currentViewId + 1, 'webview', 'foobar'),
|
||||
FakeHtmlPlatformView(currentViewId + 2, 'webview', 123),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Resize HTML view', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
final FakeHtmlPlatformViewsController viewsController = FakeHtmlPlatformViewsController();
|
||||
|
Loading…
x
Reference in New Issue
Block a user