diff --git a/packages/flutter/lib/src/widgets/platform_view.dart b/packages/flutter/lib/src/widgets/platform_view.dart index b6b0edd02f..2f04cfd2a3 100644 --- a/packages/flutter/lib/src/widgets/platform_view.dart +++ b/packages/flutter/lib/src/widgets/platform_view.dart @@ -56,8 +56,8 @@ class AndroidView extends StatefulWidget { /// /// {@template flutter.widgets.platformViews.constructorParams} /// The `viewType` and `hitTestBehavior` parameters must not be null. - /// {@endtemplate} /// If `creationParams` is not null then `creationParamsCodec` must not be null. + /// {@endtemplate} AndroidView({ // ignore: prefer_const_constructors_in_immutables // TODO(aam): Remove lint ignore above once https://dartbug.com/34297 is fixed Key key, @@ -193,8 +193,11 @@ class UiKitView extends StatefulWidget { this.onPlatformViewCreated, this.hitTestBehavior = PlatformViewHitTestBehavior.opaque, this.layoutDirection, + this.creationParams, + this.creationParamsCodec, }) : assert(viewType != null), assert(hitTestBehavior != null), + assert(creationParams == null || creationParamsCodec != null), super(key: key); // TODO(amirh): reference the iOS API doc once avaliable. @@ -212,6 +215,19 @@ class UiKitView extends StatefulWidget { /// {@macro flutter.widgets.platformViews.directionParam} final TextDirection layoutDirection; + /// Passed as the `arguments` argument of [-[FlutterPlatformViewFactory createWithFrame:viewIdentifier:arguments:]](/objcdoc/Protocols/FlutterPlatformViewFactory.html#/c:objc(pl)FlutterPlatformViewFactory(im)createWithFrame:viewIdentifier:arguments:) + /// + /// This can be used by plugins to pass constructor parameters to the embedded Android view. + final dynamic creationParams; + + /// The codec used to encode `creationParams` before sending it to the + /// platform side. It should match the codec returned by [-[FlutterPlatformViewFactory createArgsCodec:]](/objcdoc/Protocols/FlutterPlatformViewFactory.html#/c:objc(pl)FlutterPlatformViewFactory(im)createArgsCodec) + /// + /// This is typically one of: [StandardMessageCodec], [JSONMessageCodec], [StringCodec], or [BinaryCodec]. + /// + /// This must not be null if [creationParams] is not null. + final MessageCodec creationParamsCodec; + @override State createState() => _UiKitViewState(); } @@ -379,6 +395,8 @@ class _UiKitViewState extends State { id: _id, viewType: widget.viewType, layoutDirection: _layoutDirection, + creationParams: widget.creationParams, + creationParamsCodec: widget.creationParamsCodec, ); if (!mounted) { controller.dispose(); diff --git a/packages/flutter/test/services/fake_platform_views.dart b/packages/flutter/test/services/fake_platform_views.dart index 5c2ec1cd42..a075bf5a0b 100644 --- a/packages/flutter/test/services/fake_platform_views.dart +++ b/packages/flutter/test/services/fake_platform_views.dart @@ -179,6 +179,7 @@ class FakeIosPlatformViewsController { final Map args = call.arguments; final int id = args['id']; final String viewType = args['viewType']; + final Uint8List creationParams = args['params']; if (_views.containsKey(id)) { throw PlatformException( @@ -194,7 +195,7 @@ class FakeIosPlatformViewsController { ); } - _views[id] = FakeUiKitView(id, viewType); + _views[id] = FakeUiKitView(id, viewType, creationParams); return Future.sync(() => null); } @@ -228,9 +229,9 @@ class FakeAndroidPlatformView { return false; final FakeAndroidPlatformView typedOther = other; return id == typedOther.id && - type == typedOther.type && - creationParams == typedOther.creationParams && - size == typedOther.size; + type == typedOther.type && + creationParams == typedOther.creationParams && + size == typedOther.size; } @override @@ -272,10 +273,11 @@ class FakeAndroidMotionEvent { } class FakeUiKitView { - FakeUiKitView(this.id, this.type); + FakeUiKitView(this.id, this.type, [this.creationParams]); final int id; final String type; + final Uint8List creationParams; @override bool operator ==(dynamic other) { @@ -283,7 +285,8 @@ class FakeUiKitView { return false; final FakeUiKitView typedOther = other; return id == typedOther.id && - type == typedOther.type; + type == typedOther.type && + creationParams == typedOther.creationParams; } @override @@ -291,6 +294,6 @@ class FakeUiKitView { @override String toString() { - return 'FakeIosPlatformView(id: $id, type: $type)'; + return 'FakeUiKitView(id: $id, type: $type, creationParams: $creationParams)'; } } diff --git a/packages/flutter/test/widgets/platform_view_test.dart b/packages/flutter/test/widgets/platform_view_test.dart index d82e9490b0..5a0153f6be 100644 --- a/packages/flutter/test/widgets/platform_view_test.dart +++ b/packages/flutter/test/widgets/platform_view_test.dart @@ -961,5 +961,43 @@ void main() { ); }); + testWidgets('Create UIView with params', (WidgetTester tester) async { + final int currentViewId = platformViewsRegistry.getNextPlatformViewId(); + final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController(); + viewsController.registerViewType('webview'); + + await tester.pumpWidget( + Center( + child: SizedBox( + width: 200.0, + height: 100.0, + child: UiKitView( + viewType: 'webview', + layoutDirection: TextDirection.ltr, + creationParams: 'creation parameters', + creationParamsCodec: const StringCodec(), + ), + ), + ), + ); + + final FakeUiKitView fakeView = viewsController.views.first; + final Uint8List rawCreationParams = fakeView.creationParams; + final ByteData byteData = ByteData.view( + rawCreationParams.buffer, + rawCreationParams.offsetInBytes, + rawCreationParams.lengthInBytes + ); + final dynamic actualParams = const StringCodec().decodeMessage(byteData); + + expect(actualParams, 'creation parameters'); + expect( + viewsController.views, + unorderedEquals([ + FakeUiKitView(currentViewId + 1, 'webview', fakeView.creationParams) + ]), + ); + }); + }); }