Skip to content

Commit b0188cd

Browse files
authored
[web] Pass creation params to the platform view factory (flutter#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> ![image](https://github.com/flutter/flutter/assets/1278212/4b62ed8b-2314-49d6-9b4a-5da849bf2a48) Depends on flutter/engine#42255 Part of flutter#127030
1 parent 3246808 commit b0188cd

File tree

3 files changed

+57
-6
lines changed

3 files changed

+57
-6
lines changed

packages/flutter/lib/src/widgets/platform_view.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ class HtmlElementView extends StatelessWidget {
345345
super.key,
346346
required this.viewType,
347347
this.onPlatformViewCreated,
348+
this.creationParams,
348349
}) : assert(kIsWeb, 'HtmlElementView is only available on Flutter Web.');
349350

350351
/// The unique identifier for the HTML view type to be embedded by this widget.
@@ -357,6 +358,9 @@ class HtmlElementView extends StatelessWidget {
357358
/// May be null.
358359
final PlatformViewCreatedCallback? onPlatformViewCreated;
359360

361+
/// Passed as the 2nd argument (i.e. `params`) of the registered view factory.
362+
final Object? creationParams;
363+
360364
@override
361365
Widget build(BuildContext context) {
362366
return PlatformViewLink(
@@ -374,7 +378,11 @@ class HtmlElementView extends StatelessWidget {
374378

375379
/// Creates the controller and kicks off its initialization.
376380
_HtmlElementViewController _createHtmlElementView(PlatformViewCreationParams params) {
377-
final _HtmlElementViewController controller = _HtmlElementViewController(params.id, viewType);
381+
final _HtmlElementViewController controller = _HtmlElementViewController(
382+
params.id,
383+
viewType,
384+
creationParams,
385+
);
378386
controller._initialize().then((_) {
379387
params.onPlatformViewCreated(params.id);
380388
onPlatformViewCreated?.call(params.id);
@@ -387,6 +395,7 @@ class _HtmlElementViewController extends PlatformViewController {
387395
_HtmlElementViewController(
388396
this.viewId,
389397
this.viewType,
398+
this.creationParams,
390399
);
391400

392401
@override
@@ -397,12 +406,15 @@ class _HtmlElementViewController extends PlatformViewController {
397406
/// A PlatformViewFactory for this type must have been registered.
398407
final String viewType;
399408

409+
final dynamic creationParams;
410+
400411
bool _initialized = false;
401412

402413
Future<void> _initialize() async {
403414
final Map<String, dynamic> args = <String, dynamic>{
404415
'id': viewId,
405416
'viewType': viewType,
417+
'params': creationParams,
406418
};
407419
await SystemChannels.platform_views.invokeMethod<void>('create', args);
408420
_initialized = true;

packages/flutter/test/services/fake_platform_views.dart

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ class FakeHtmlPlatformViewsController {
503503
final Map<dynamic, dynamic> args = call.arguments as Map<dynamic, dynamic>;
504504
final int id = args['id'] as int;
505505
final String viewType = args['viewType'] as String;
506+
final Object? params = args['params'];
506507

507508
if (_views.containsKey(id)) {
508509
throw PlatformException(
@@ -522,7 +523,7 @@ class FakeHtmlPlatformViewsController {
522523
await createCompleter!.future;
523524
}
524525

525-
_views[id] = FakeHtmlPlatformView(id, viewType);
526+
_views[id] = FakeHtmlPlatformView(id, viewType, params);
526527
return Future<int?>.sync(() => null);
527528
}
528529

@@ -658,10 +659,11 @@ class FakeUiKitView {
658659

659660
@immutable
660661
class FakeHtmlPlatformView {
661-
const FakeHtmlPlatformView(this.id, this.type);
662+
const FakeHtmlPlatformView(this.id, this.type, [this.creationParams]);
662663

663664
final int id;
664665
final String type;
666+
final Object? creationParams;
665667

666668
@override
667669
bool operator ==(Object other) {
@@ -670,14 +672,15 @@ class FakeHtmlPlatformView {
670672
}
671673
return other is FakeHtmlPlatformView
672674
&& other.id == id
673-
&& other.type == type;
675+
&& other.type == type
676+
&& other.creationParams == creationParams;
674677
}
675678

676679
@override
677-
int get hashCode => Object.hash(id, type);
680+
int get hashCode => Object.hash(id, type, creationParams);
678681

679682
@override
680683
String toString() {
681-
return 'FakeHtmlPlatformView(id: $id, type: $type)';
684+
return 'FakeHtmlPlatformView(id: $id, type: $type, params: $creationParams)';
682685
}
683686
}

packages/flutter/test/widgets/html_element_view_test.dart

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,42 @@ void main() {
7373
);
7474
});
7575

76+
testWidgets('Create HTML view with creation params', (WidgetTester tester) async {
77+
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
78+
final FakeHtmlPlatformViewsController viewsController = FakeHtmlPlatformViewsController();
79+
viewsController.registerViewType('webview');
80+
await tester.pumpWidget(
81+
const Column(
82+
children: <Widget>[
83+
SizedBox(
84+
width: 200.0,
85+
height: 100.0,
86+
child: HtmlElementView(
87+
viewType: 'webview',
88+
creationParams: 'foobar',
89+
),
90+
),
91+
SizedBox(
92+
width: 200.0,
93+
height: 100.0,
94+
child: HtmlElementView(
95+
viewType: 'webview',
96+
creationParams: 123,
97+
),
98+
),
99+
],
100+
),
101+
);
102+
103+
expect(
104+
viewsController.views,
105+
unorderedEquals(<FakeHtmlPlatformView>[
106+
FakeHtmlPlatformView(currentViewId + 1, 'webview', 'foobar'),
107+
FakeHtmlPlatformView(currentViewId + 2, 'webview', 123),
108+
]),
109+
);
110+
});
111+
76112
testWidgets('Resize HTML view', (WidgetTester tester) async {
77113
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
78114
final FakeHtmlPlatformViewsController viewsController = FakeHtmlPlatformViewsController();

0 commit comments

Comments
 (0)