Wait for non-empty layout in platform view placeholder (#112402)
diff --git a/packages/flutter/lib/src/widgets/platform_view.dart b/packages/flutter/lib/src/widgets/platform_view.dart
index f26d690..982cbc2 100644
--- a/packages/flutter/lib/src/widgets/platform_view.dart
+++ b/packages/flutter/lib/src/widgets/platform_view.dart
@@ -877,10 +877,10 @@
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 ea728f6..12b7aaa 100644
--- a/packages/flutter/test/services/fake_platform_views.dart
+++ b/packages/flutter/test/services/fake_platform_views.dart
@@ -133,6 +133,9 @@
@override
Future<void> 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 7af5329..f4fb1d2 100644
--- a/packages/flutter/test/widgets/platform_view_test.dart
+++ b/packages/flutter/test/widgets/platform_view_test.dart
@@ -2503,6 +2503,48 @@
);
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 <Factory<OneSequenceGestureRecognizer>>{},
+ controller: controller,
+ hitTestBehavior: PlatformViewHitTestBehavior.opaque,
+ );
+ },
+ )
+ ));
+
+ await tester.pumpWidget(widget);
+
+ expect(
+ tester.allWidgets.map((Widget widget) => widget.runtimeType.toString()).toList(),
+ equals(<String>['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 {
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
@@ -2541,6 +2583,9 @@
equals(<String>['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();
@@ -2551,7 +2596,6 @@
);
expect(createdPlatformViewId, currentViewId + 1);
- expect(controller.awaitingCreation, false);
},
);