diff --git a/packages/flutter/lib/src/widgets/platform_view.dart b/packages/flutter/lib/src/widgets/platform_view.dart index 0a9721fd640..798ef0953ad 100644 --- a/packages/flutter/lib/src/widgets/platform_view.dart +++ b/packages/flutter/lib/src/widgets/platform_view.dart @@ -869,10 +869,10 @@ class _PlatformViewLinkState extends State { return const SizedBox.expand(); } if (!_platformViewCreated) { - // Depending on the implementation, the initial size can be used to size - // the platform view. + // Depending on the implementation, the first non-empty size can be used + // to size the platform view. return _PlatformViewPlaceHolder(onLayout: (Size size) { - if (controller.awaitingCreation) { + if (controller.awaitingCreation && !size.isEmpty) { controller.create(size: size); } }); diff --git a/packages/flutter/test/services/fake_platform_views.dart b/packages/flutter/test/services/fake_platform_views.dart index 52104788023..0d80150ad7e 100644 --- a/packages/flutter/test/services/fake_platform_views.dart +++ b/packages/flutter/test/services/fake_platform_views.dart @@ -124,6 +124,9 @@ class FakeAndroidViewController implements AndroidViewController { @override Future create({Size? size}) async { assert(!_createCalledSuccessfully); + if (requiresSize && size != null) { + assert(!size.isEmpty); + } _createCalledSuccessfully = size != null || !requiresSize; } diff --git a/packages/flutter/test/widgets/platform_view_test.dart b/packages/flutter/test/widgets/platform_view_test.dart index 7c15a7bef09..e503219d3f2 100644 --- a/packages/flutter/test/widgets/platform_view_test.dart +++ b/packages/flutter/test/widgets/platform_view_test.dart @@ -2455,6 +2455,48 @@ void main() { }, ); + testWidgets( + 'PlatformViewLink widget should not trigger creation with an empty size', + (WidgetTester tester) async { + late PlatformViewController controller; + + final Widget widget = Center(child: SizedBox( + height: 0, + child: PlatformViewLink( + viewType: 'webview', + onCreatePlatformView: (PlatformViewCreationParams params) { + controller = FakeAndroidViewController(params.id, requiresSize: true); + controller.create(); + // This test should be simulating one of the texture-based display + // modes, where `create` is a no-op when not provided a size, and + // creation is triggered via a later call to setSize, or to `create` + // with a size. + expect(controller.awaitingCreation, true); + return controller; + }, + surfaceFactory: (BuildContext context, PlatformViewController controller) { + return PlatformViewSurface( + gestureRecognizers: const >{}, + controller: controller, + hitTestBehavior: PlatformViewHitTestBehavior.opaque, + ); + }, + ) + )); + + await tester.pumpWidget(widget); + + expect( + tester.allWidgets.map((Widget widget) => widget.runtimeType.toString()).toList(), + equals(['Center', 'SizedBox', 'PlatformViewLink', '_PlatformViewPlaceHolder']), + ); + + // 'create' should not have been called by PlatformViewLink, since its + // size is empty. + expect(controller.awaitingCreation, true); + }, + ); + testWidgets( 'PlatformViewLink calls create when needed for Android texture display modes', (WidgetTester tester) async { @@ -2494,6 +2536,9 @@ void main() { equals(['PlatformViewLink', '_PlatformViewPlaceHolder']), ); + // Layout should have triggered a create call. Simulate the callback + // that the real controller would make after creation. + expect(controller.awaitingCreation, false); onPlatformViewCreatedCallBack(createdPlatformViewId); await tester.pump(); @@ -2504,7 +2549,6 @@ void main() { ); expect(createdPlatformViewId, currentViewId + 1); - expect(controller.awaitingCreation, false); }, );