Unverified Commit 19680c34 authored by Emmanuel Garcia's avatar Emmanuel Garcia Committed by GitHub

Revert "Reland: "Always use texture layer when displaying an Android view" (#100237)" (#100660)

This reverts commit d92fedcc.
parent 6e13f3d7
...@@ -76,9 +76,11 @@ Future<void> main() async { ...@@ -76,9 +76,11 @@ Future<void> main() async {
expect( expect(
await driver.requestData('hierarchy'), await driver.requestData('hierarchy'),
'|-FlutterView\n' '|-FlutterView\n'
' |-FlutterSurfaceView\n' // Flutter UI ' |-FlutterSurfaceView\n' // Flutter UI (hidden)
' |-FlutterImageView\n' // Flutter UI (background surface)
' |-ViewGroup\n' // Platform View ' |-ViewGroup\n' // Platform View
' |-ViewGroup\n' ' |-ViewGroup\n'
' |-FlutterImageView\n' // Flutter UI (overlay surface)
); );
// Hide platform view. // Hide platform view.
...@@ -99,9 +101,11 @@ Future<void> main() async { ...@@ -99,9 +101,11 @@ Future<void> main() async {
expect( expect(
await driver.requestData('hierarchy'), await driver.requestData('hierarchy'),
'|-FlutterView\n' '|-FlutterView\n'
' |-FlutterSurfaceView\n' // Flutter UI ' |-FlutterSurfaceView\n' // Flutter UI (hidden)
' |-FlutterImageView\n' // Flutter UI (background surface)
' |-ViewGroup\n' // Platform View ' |-ViewGroup\n' // Platform View
' |-ViewGroup\n' ' |-ViewGroup\n'
' |-FlutterImageView\n' // Flutter UI (overlay surface)
); );
}, timeout: Timeout.none); }, timeout: Timeout.none);
}); });
......
...@@ -52,7 +52,7 @@ Set<Type> _factoriesTypeSet<T>(Set<Factory<T>> factories) { ...@@ -52,7 +52,7 @@ Set<Type> _factoriesTypeSet<T>(Set<Factory<T>> factories) {
/// A render object for an Android view. /// A render object for an Android view.
/// ///
/// Requires Android API level 23 or greater. /// Requires Android API level 20 or greater.
/// ///
/// [RenderAndroidView] is responsible for sizing, displaying and passing touch events to an /// [RenderAndroidView] is responsible for sizing, displaying and passing touch events to an
/// Android [View](https://developer.android.com/reference/android/view/View). /// Android [View](https://developer.android.com/reference/android/view/View).
...@@ -74,7 +74,7 @@ Set<Type> _factoriesTypeSet<T>(Set<Factory<T>> factories) { ...@@ -74,7 +74,7 @@ Set<Type> _factoriesTypeSet<T>(Set<Factory<T>> factories) {
/// ///
/// * [AndroidView] which is a widget that is used to show an Android view. /// * [AndroidView] which is a widget that is used to show an Android view.
/// * [PlatformViewsService] which is a service for controlling platform views. /// * [PlatformViewsService] which is a service for controlling platform views.
class RenderAndroidView extends PlatformViewRenderBox { class RenderAndroidView extends RenderBox with _PlatformViewGestureMixin {
/// Creates a render object for an Android view. /// Creates a render object for an Android view.
RenderAndroidView({ RenderAndroidView({
required AndroidViewController viewController, required AndroidViewController viewController,
...@@ -86,8 +86,7 @@ class RenderAndroidView extends PlatformViewRenderBox { ...@@ -86,8 +86,7 @@ class RenderAndroidView extends PlatformViewRenderBox {
assert(gestureRecognizers != null), assert(gestureRecognizers != null),
assert(clipBehavior != null), assert(clipBehavior != null),
_viewController = viewController, _viewController = viewController,
_clipBehavior = clipBehavior, _clipBehavior = clipBehavior {
super(controller: viewController, hitTestBehavior: hitTestBehavior, gestureRecognizers: gestureRecognizers) {
_viewController.pointTransformer = (Offset offset) => globalToLocal(offset); _viewController.pointTransformer = (Offset offset) => globalToLocal(offset);
updateGestureRecognizers(gestureRecognizers); updateGestureRecognizers(gestureRecognizers);
_viewController.addOnPlatformViewCreatedListener(_onPlatformViewCreated); _viewController.addOnPlatformViewCreatedListener(_onPlatformViewCreated);
...@@ -102,22 +101,18 @@ class RenderAndroidView extends PlatformViewRenderBox { ...@@ -102,22 +101,18 @@ class RenderAndroidView extends PlatformViewRenderBox {
bool _isDisposed = false; bool _isDisposed = false;
/// The Android view controller for the Android view associated with this render object. /// The Android view controller for the Android view associated with this render object.
@override AndroidViewController get viewController => _viewController;
AndroidViewController get controller => _viewController;
AndroidViewController _viewController; AndroidViewController _viewController;
/// Sets a new Android view controller. /// Sets a new Android view controller.
@override ///
set controller(AndroidViewController controller) { /// `viewController` must not be null.
set viewController(AndroidViewController viewController) {
assert(_viewController != null); assert(_viewController != null);
assert(controller != null); assert(viewController != null);
if (_viewController == controller) if (_viewController == viewController)
return; return;
_viewController.removeOnPlatformViewCreatedListener(_onPlatformViewCreated); _viewController.removeOnPlatformViewCreatedListener(_onPlatformViewCreated);
super.controller = controller; _viewController = viewController;
_viewController = controller;
_viewController.pointTransformer = (Offset offset) => globalToLocal(offset);
_sizePlatformView(); _sizePlatformView();
if (_viewController.isCreated) { if (_viewController.isCreated) {
markNeedsSemanticsUpdate(); markNeedsSemanticsUpdate();
...@@ -143,6 +138,26 @@ class RenderAndroidView extends PlatformViewRenderBox { ...@@ -143,6 +138,26 @@ class RenderAndroidView extends PlatformViewRenderBox {
markNeedsSemanticsUpdate(); markNeedsSemanticsUpdate();
} }
/// {@template flutter.rendering.RenderAndroidView.updateGestureRecognizers}
/// Updates which gestures should be forwarded to the platform view.
///
/// Gesture recognizers created by factories in this set participate in the gesture arena for each
/// pointer that was put down on the render box. If any of the recognizers on this list wins the
/// gesture arena, the entire pointer event sequence starting from the pointer down event
/// will be dispatched to the Android view.
///
/// The `gestureRecognizers` property must not contain more than one factory with the same [Factory.type].
///
/// Setting a new set of gesture recognizer factories with the same [Factory.type]s as the current
/// set has no effect, because the factories' constructors would have already been called with the previous set.
/// {@endtemplate}
///
/// Any active gesture arena the Android view participates in is rejected when the
/// set of gesture recognizers is changed.
void updateGestureRecognizers(Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers) {
_updateGestureRecognizersWithCallBack(gestureRecognizers, _viewController.dispatchPointerEvent);
}
@override @override
bool get sizedByParent => true; bool get sizedByParent => true;
...@@ -167,8 +182,9 @@ class RenderAndroidView extends PlatformViewRenderBox { ...@@ -167,8 +182,9 @@ class RenderAndroidView extends PlatformViewRenderBox {
// Android virtual displays cannot have a zero size. // Android virtual displays cannot have a zero size.
// Trying to size it to 0 crashes the app, which was happening when starting the app // Trying to size it to 0 crashes the app, which was happening when starting the app
// with a locked screen (see: https://github.com/flutter/flutter/issues/20456). // with a locked screen (see: https://github.com/flutter/flutter/issues/20456).
if (_state == _PlatformViewState.resizing || size.isEmpty) if (_state == _PlatformViewState.resizing || size.isEmpty) {
return; return;
}
_state = _PlatformViewState.resizing; _state = _PlatformViewState.resizing;
markNeedsPaint(); markNeedsPaint();
...@@ -196,8 +212,7 @@ class RenderAndroidView extends PlatformViewRenderBox { ...@@ -196,8 +212,7 @@ class RenderAndroidView extends PlatformViewRenderBox {
void _setOffset() { void _setOffset() {
SchedulerBinding.instance.addPostFrameCallback((_) async { SchedulerBinding.instance.addPostFrameCallback((_) async {
if (!_isDisposed) { if (!_isDisposed) {
if (attached) await _viewController.setOffset(localToGlobal(Offset.zero));
await _viewController.setOffset(localToGlobal(Offset.zero));
// Schedule a new post frame callback. // Schedule a new post frame callback.
_setOffset(); _setOffset();
} }
...@@ -206,7 +221,7 @@ class RenderAndroidView extends PlatformViewRenderBox { ...@@ -206,7 +221,7 @@ class RenderAndroidView extends PlatformViewRenderBox {
@override @override
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
if (_viewController.textureId == null || _currentTextureSize == null) if (_viewController.textureId == null)
return; return;
// As resizing the Android view happens asynchronously we don't know exactly when is a // As resizing the Android view happens asynchronously we don't know exactly when is a
...@@ -249,15 +264,14 @@ class RenderAndroidView extends PlatformViewRenderBox { ...@@ -249,15 +264,14 @@ class RenderAndroidView extends PlatformViewRenderBox {
context.addLayer(TextureLayer( context.addLayer(TextureLayer(
rect: offset & _currentTextureSize!, rect: offset & _currentTextureSize!,
textureId: _viewController.textureId!, textureId: viewController.textureId!,
)); ));
} }
@override @override
void describeSemanticsConfiguration(SemanticsConfiguration config) { void describeSemanticsConfiguration (SemanticsConfiguration config) {
// Don't call the super implementation since `platformViewId` should super.describeSemanticsConfiguration(config);
// be set only when the platform view is created, but the concept of
// a "created" platform view belongs to this subclass.
config.isSemanticBoundary = true; config.isSemanticBoundary = true;
if (_viewController.isCreated) { if (_viewController.isCreated) {
...@@ -325,7 +339,7 @@ class RenderUiKitView extends RenderBox { ...@@ -325,7 +339,7 @@ class RenderUiKitView extends RenderBox {
// any newly arriving events there's nothing we need to invalidate. // any newly arriving events there's nothing we need to invalidate.
PlatformViewHitTestBehavior hitTestBehavior; PlatformViewHitTestBehavior hitTestBehavior;
/// {@macro flutter.rendering.PlatformViewRenderBox.updateGestureRecognizers} /// {@macro flutter.rendering.RenderAndroidView.updateGestureRecognizers}
void updateGestureRecognizers(Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers) { void updateGestureRecognizers(Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers) {
assert(gestureRecognizers != null); assert(gestureRecognizers != null);
assert( assert(
...@@ -639,11 +653,11 @@ class PlatformViewRenderBox extends RenderBox with _PlatformViewGestureMixin { ...@@ -639,11 +653,11 @@ class PlatformViewRenderBox extends RenderBox with _PlatformViewGestureMixin {
PlatformViewController get controller => _controller; PlatformViewController get controller => _controller;
PlatformViewController _controller; PlatformViewController _controller;
/// This value must not be null, and setting it to a new value will result in a repaint. /// This value must not be null, and setting it to a new value will result in a repaint.
set controller(covariant PlatformViewController controller) { set controller(PlatformViewController controller) {
assert(controller != null); assert(controller != null);
assert(controller.viewId != null && controller.viewId > -1); assert(controller.viewId != null && controller.viewId > -1);
if (_controller == controller) { if ( _controller == controller) {
return; return;
} }
final bool needsSemanticsUpdate = _controller.viewId != controller.viewId; final bool needsSemanticsUpdate = _controller.viewId != controller.viewId;
...@@ -654,19 +668,7 @@ class PlatformViewRenderBox extends RenderBox with _PlatformViewGestureMixin { ...@@ -654,19 +668,7 @@ class PlatformViewRenderBox extends RenderBox with _PlatformViewGestureMixin {
} }
} }
/// {@template flutter.rendering.PlatformViewRenderBox.updateGestureRecognizers} /// {@macro flutter.rendering.RenderAndroidView.updateGestureRecognizers}
/// Updates which gestures should be forwarded to the platform view.
///
/// Gesture recognizers created by factories in this set participate in the gesture arena for each
/// pointer that was put down on the render box. If any of the recognizers on this list wins the
/// gesture arena, the entire pointer event sequence starting from the pointer down event
/// will be dispatched to the Android view.
///
/// The `gestureRecognizers` property must not contain more than one factory with the same [Factory.type].
///
/// Setting a new set of gesture recognizer factories with the same [Factory.type]s as the current
/// set has no effect, because the factories' constructors would have already been called with the previous set.
/// {@endtemplate}
/// ///
/// Any active gesture arena the `PlatformView` participates in is rejected when the /// Any active gesture arena the `PlatformView` participates in is rejected when the
/// set of gesture recognizers is changed. /// set of gesture recognizers is changed.
...@@ -698,7 +700,7 @@ class PlatformViewRenderBox extends RenderBox with _PlatformViewGestureMixin { ...@@ -698,7 +700,7 @@ class PlatformViewRenderBox extends RenderBox with _PlatformViewGestureMixin {
} }
@override @override
void describeSemanticsConfiguration(SemanticsConfiguration config) { void describeSemanticsConfiguration (SemanticsConfiguration config) {
super.describeSemanticsConfiguration(config); super.describeSemanticsConfiguration(config);
assert(_controller.viewId != null); assert(_controller.viewId != null);
config.isSemanticBoundary = true; config.isSemanticBoundary = true;
......
...@@ -15,7 +15,7 @@ import 'framework.dart'; ...@@ -15,7 +15,7 @@ import 'framework.dart';
/// Embeds an Android view in the Widget hierarchy. /// Embeds an Android view in the Widget hierarchy.
/// ///
/// Requires Android API level 23 or greater. /// Requires Android API level 20 or greater.
/// ///
/// Embedding Android views is an expensive operation and should be avoided when a Flutter /// Embedding Android views is an expensive operation and should be avoided when a Flutter
/// equivalent is possible. /// equivalent is possible.
...@@ -681,7 +681,7 @@ class _AndroidPlatformView extends LeafRenderObjectWidget { ...@@ -681,7 +681,7 @@ class _AndroidPlatformView extends LeafRenderObjectWidget {
@override @override
void updateRenderObject(BuildContext context, RenderAndroidView renderObject) { void updateRenderObject(BuildContext context, RenderAndroidView renderObject) {
renderObject.controller = controller; renderObject.viewController = controller;
renderObject.hitTestBehavior = hitTestBehavior; renderObject.hitTestBehavior = hitTestBehavior;
renderObject.updateGestureRecognizers(gestureRecognizers); renderObject.updateGestureRecognizers(gestureRecognizers);
renderObject.clipBehavior = clipBehavior; renderObject.clipBehavior = clipBehavior;
...@@ -842,11 +842,15 @@ class PlatformViewLink extends StatefulWidget { ...@@ -842,11 +842,15 @@ class PlatformViewLink extends StatefulWidget {
class _PlatformViewLinkState extends State<PlatformViewLink> { class _PlatformViewLinkState extends State<PlatformViewLink> {
int? _id; int? _id;
PlatformViewController? _controller; PlatformViewController? _controller;
bool _platformViewCreated = false;
Widget? _surface; Widget? _surface;
FocusNode? _focusNode; FocusNode? _focusNode;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (!_platformViewCreated) {
return const SizedBox.expand();
}
_surface ??= widget._surfaceFactory(context, _controller!); _surface ??= widget._surfaceFactory(context, _controller!);
return Focus( return Focus(
focusNode: _focusNode, focusNode: _focusNode,
...@@ -871,6 +875,9 @@ class _PlatformViewLinkState extends State<PlatformViewLink> { ...@@ -871,6 +875,9 @@ class _PlatformViewLinkState extends State<PlatformViewLink> {
// The _surface has to be recreated as its controller is disposed. // The _surface has to be recreated as its controller is disposed.
// Setting _surface to null will trigger its creation in build(). // Setting _surface to null will trigger its creation in build().
_surface = null; _surface = null;
// We are about to create a new platform view.
_platformViewCreated = false;
_initialize(); _initialize();
} }
} }
...@@ -881,12 +888,16 @@ class _PlatformViewLinkState extends State<PlatformViewLink> { ...@@ -881,12 +888,16 @@ class _PlatformViewLinkState extends State<PlatformViewLink> {
PlatformViewCreationParams._( PlatformViewCreationParams._(
id: _id!, id: _id!,
viewType: widget.viewType, viewType: widget.viewType,
onPlatformViewCreated: (_) {}, onPlatformViewCreated: _onPlatformViewCreated,
onFocusChanged: _handlePlatformFocusChanged, onFocusChanged: _handlePlatformFocusChanged,
), ),
); );
} }
void _onPlatformViewCreated(int id) {
setState(() { _platformViewCreated = true; });
}
void _handleFrameworkFocusChanged(bool isFocused) { void _handleFrameworkFocusChanged(bool isFocused) {
if (!isFocused) { if (!isFocused) {
_controller?.clearFocus(); _controller?.clearFocus();
...@@ -1009,18 +1020,18 @@ class PlatformViewSurface extends LeafRenderObjectWidget { ...@@ -1009,18 +1020,18 @@ class PlatformViewSurface extends LeafRenderObjectWidget {
/// Integrates an Android view with Flutter's compositor, touch, and semantics subsystems. /// Integrates an Android view with Flutter's compositor, touch, and semantics subsystems.
/// ///
/// The compositor integration is done by adding a [TextureLayer] to the layer tree. /// The compositor integration is done by adding a [PlatformViewLayer] to the layer tree. [PlatformViewLayer]
/// isn't supported on all platforms. Custom Flutter embedders can support
/// [PlatformViewLayer]s by implementing a SystemCompositor.
/// ///
/// The parent of this object must provide bounded layout constraints. /// The widget fills all available space, the parent of this object must provide bounded layout
/// constraints.
/// ///
/// If the associated platform view is not created, the [AndroidViewSurface] does not paint any contents. /// If the associated platform view is not created, the [AndroidViewSurface] does not paint any contents.
/// ///
/// When possible, you may want to use [AndroidView] directly, since it requires less boilerplate code
/// than [AndroidViewSurface], and there's no difference in performance, or other trade-off(s).
///
/// See also: /// See also:
/// ///
/// * [AndroidView] which embeds an Android platform view in the widget hierarchy. /// * [AndroidView] which embeds an Android platform view in the widget hierarchy using a [TextureLayer].
/// * [UiKitView] which embeds an iOS platform view in the widget hierarchy. /// * [UiKitView] which embeds an iOS platform view in the widget hierarchy.
class AndroidViewSurface extends PlatformViewSurface { class AndroidViewSurface extends PlatformViewSurface {
/// Construct an `AndroidPlatformViewSurface`. /// Construct an `AndroidPlatformViewSurface`.
...@@ -1041,22 +1052,12 @@ class AndroidViewSurface extends PlatformViewSurface { ...@@ -1041,22 +1052,12 @@ class AndroidViewSurface extends PlatformViewSurface {
@override @override
RenderObject createRenderObject(BuildContext context) { RenderObject createRenderObject(BuildContext context) {
final AndroidViewController viewController = controller as AndroidViewController; final PlatformViewRenderBox renderBox =
final RenderAndroidView renderObject = RenderAndroidView( super.createRenderObject(context) as PlatformViewRenderBox;
viewController: viewController,
gestureRecognizers: gestureRecognizers,
hitTestBehavior: hitTestBehavior,
);
viewController.pointTransformer =
(Offset position) => renderObject.globalToLocal(position);
return renderObject;
}
@override (controller as AndroidViewController).pointTransformer =
void updateRenderObject(BuildContext context, RenderAndroidView renderObject) { (Offset position) => renderBox.globalToLocal(position);
renderObject
..controller = controller as AndroidViewController return renderBox;
..hitTestBehavior = hitTestBehavior
..updateGestureRecognizers(gestureRecognizers);
} }
} }
...@@ -151,38 +151,6 @@ void main() { ...@@ -151,38 +151,6 @@ void main() {
// Passes if no crashes. // Passes if no crashes.
}); });
test('created callback is reset when controller is changed', () {
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
viewsController.registerViewType('webview');
final AndroidViewController firstController = PlatformViewsService.initAndroidView(
id: 0,
viewType: 'webview',
layoutDirection: TextDirection.rtl,
);
final RenderAndroidView renderBox = RenderAndroidView(
viewController: firstController,
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{},
);
layout(renderBox);
pumpFrame(phase: EnginePhase.flushSemantics);
expect(firstController.createdCallbacks, isNotEmpty);
expect(firstController.createdCallbacks.length, 1);
final AndroidViewController secondController = PlatformViewsService.initAndroidView(
id: 0,
viewType: 'webview',
layoutDirection: TextDirection.rtl,
);
// Reset controller.
renderBox.controller = secondController;
expect(firstController.createdCallbacks, isEmpty);
expect(secondController.createdCallbacks, isNotEmpty);
expect(secondController.createdCallbacks.length, 1);
});
test('render object changed its visual appearance after texture is created', () { test('render object changed its visual appearance after texture is created', () {
FakeAsync().run((FakeAsync async) { FakeAsync().run((FakeAsync async) {
final AndroidViewController viewController = final AndroidViewController viewController =
......
...@@ -84,22 +84,23 @@ class FakeAndroidViewController implements AndroidViewController { ...@@ -84,22 +84,23 @@ class FakeAndroidViewController implements AndroidViewController {
@override @override
Future<Size> setSize(Size size) { Future<Size> setSize(Size size) {
return Future<Size>.value(size); throw UnimplementedError();
} }
@override @override
Future<void> setOffset(Offset off) async {} Future<void> setOffset(Offset off) {
throw UnimplementedError();
}
@override @override
int get textureId => 0; int get textureId => throw UnimplementedError();
@override @override
bool get isCreated => created; bool get isCreated => throw UnimplementedError();
@override @override
void addOnPlatformViewCreatedListener(PlatformViewCreatedCallback listener) { void addOnPlatformViewCreatedListener(PlatformViewCreatedCallback listener) =>
created = true; throw UnimplementedError();
}
@override @override
void removeOnPlatformViewCreatedListener(PlatformViewCreatedCallback listener) { void removeOnPlatformViewCreatedListener(PlatformViewCreatedCallback listener) {
...@@ -117,10 +118,9 @@ class FakeAndroidViewController implements AndroidViewController { ...@@ -117,10 +118,9 @@ class FakeAndroidViewController implements AndroidViewController {
} }
@override @override
Future<void> create() async {} Future<void> create() async {
created = true;
@override }
List<PlatformViewCreatedCallback> get createdCallbacks => <PlatformViewCreatedCallback>[];
} }
class FakeAndroidPlatformViewsController { class FakeAndroidPlatformViewsController {
...@@ -143,6 +143,8 @@ class FakeAndroidPlatformViewsController { ...@@ -143,6 +143,8 @@ class FakeAndroidPlatformViewsController {
int? lastClearedFocusViewId; int? lastClearedFocusViewId;
bool synchronizeToNativeViewHierarchy = true;
Map<int, Offset> offsets = <int, Offset>{}; Map<int, Offset> offsets = <int, Offset>{};
void registerViewType(String viewType) { void registerViewType(String viewType) {
...@@ -172,6 +174,8 @@ class FakeAndroidPlatformViewsController { ...@@ -172,6 +174,8 @@ class FakeAndroidPlatformViewsController {
return _clearFocus(call); return _clearFocus(call);
case 'offset': case 'offset':
return _offset(call); return _offset(call);
case 'synchronizeToNativeViewHierarchy':
return _synchronizeToNativeViewHierarchy(call);
} }
return Future<dynamic>.sync(() => null); return Future<dynamic>.sync(() => null);
} }
...@@ -314,6 +318,11 @@ class FakeAndroidPlatformViewsController { ...@@ -314,6 +318,11 @@ class FakeAndroidPlatformViewsController {
lastClearedFocusViewId = id; lastClearedFocusViewId = id;
return Future<dynamic>.sync(() => null); return Future<dynamic>.sync(() => null);
} }
Future<dynamic> _synchronizeToNativeViewHierarchy(MethodCall call) {
synchronizeToNativeViewHierarchy = call.arguments as bool;
return Future<dynamic>.sync(() => null);
}
} }
class FakeIosPlatformViewsController { class FakeIosPlatformViewsController {
......
...@@ -18,7 +18,7 @@ void main() { ...@@ -18,7 +18,7 @@ void main() {
}); });
test('create Android view of unregistered type', () async { test('create Android view of unregistered type', () async {
expectLater( expect(
() { () {
return PlatformViewsService.initAndroidView( return PlatformViewsService.initAndroidView(
id: 0, id: 0,
...@@ -29,25 +29,16 @@ void main() { ...@@ -29,25 +29,16 @@ void main() {
throwsA(isA<PlatformException>()), throwsA(isA<PlatformException>()),
); );
try { expect(
await PlatformViewsService.initSurfaceAndroidView( () {
id: 0, return PlatformViewsService.initSurfaceAndroidView(
viewType: 'web', id: 0,
layoutDirection: TextDirection.ltr, viewType: 'web',
).create(); layoutDirection: TextDirection.ltr,
} catch (e) { ).create();
expect(false, isTrue, reason: 'did not expected any exception, but instead got `$e`'); },
} throwsA(isA<PlatformException>()),
);
try {
await PlatformViewsService.initAndroidView(
id: 0,
viewType: 'web',
layoutDirection: TextDirection.ltr,
).create();
} catch (e) {
expect(false, isTrue, reason: 'did not expected any exception, but instead got `$e`');
}
}); });
test('create Android views', () async { test('create Android views', () async {
...@@ -56,13 +47,13 @@ void main() { ...@@ -56,13 +47,13 @@ void main() {
.setSize(const Size(100.0, 100.0)); .setSize(const Size(100.0, 100.0));
await PlatformViewsService.initAndroidView( id: 1, viewType: 'webview', layoutDirection: TextDirection.rtl) await PlatformViewsService.initAndroidView( id: 1, viewType: 'webview', layoutDirection: TextDirection.rtl)
.setSize(const Size(200.0, 300.0)); .setSize(const Size(200.0, 300.0));
// This platform view isn't created until the size is set.
await PlatformViewsService.initSurfaceAndroidView(id: 2, viewType: 'webview', layoutDirection: TextDirection.rtl).create(); await PlatformViewsService.initSurfaceAndroidView(id: 2, viewType: 'webview', layoutDirection: TextDirection.rtl).create();
expect( expect(
viewsController.views, viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[ unorderedEquals(<FakeAndroidPlatformView>[
const FakeAndroidPlatformView(0, 'webview', Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr, null), const FakeAndroidPlatformView(0, 'webview', Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr, null),
const FakeAndroidPlatformView(1, 'webview', Size(200.0, 300.0), AndroidViewController.kAndroidLayoutDirectionRtl, null), const FakeAndroidPlatformView(1, 'webview', Size(200.0, 300.0), AndroidViewController.kAndroidLayoutDirectionRtl, null),
const FakeAndroidPlatformView(2, 'webview', null, AndroidViewController.kAndroidLayoutDirectionRtl, true),
]), ]),
); );
}); });
...@@ -74,7 +65,7 @@ void main() { ...@@ -74,7 +65,7 @@ void main() {
viewType: 'webview', viewType: 'webview',
layoutDirection: TextDirection.ltr, layoutDirection: TextDirection.ltr,
).setSize(const Size(100.0, 100.0)); ).setSize(const Size(100.0, 100.0));
expectLater( expect(
() => PlatformViewsService.initAndroidView( () => PlatformViewsService.initAndroidView(
id: 0, id: 0,
viewType: 'web', viewType: 'web',
...@@ -82,6 +73,20 @@ void main() { ...@@ -82,6 +73,20 @@ void main() {
).setSize(const Size(100.0, 100.0)), ).setSize(const Size(100.0, 100.0)),
throwsA(isA<PlatformException>()), throwsA(isA<PlatformException>()),
); );
await PlatformViewsService.initSurfaceAndroidView(
id: 1,
viewType: 'webview',
layoutDirection: TextDirection.ltr,
).create();
expect(
() => PlatformViewsService.initSurfaceAndroidView(
id: 1,
viewType: 'web',
layoutDirection: TextDirection.ltr,
).create(),
throwsA(isA<PlatformException>()),
);
}); });
test('dispose Android view', () async { test('dispose Android view', () async {
...@@ -235,6 +240,11 @@ void main() { ...@@ -235,6 +240,11 @@ void main() {
await viewController.setOffset(const Offset(10, 20)); await viewController.setOffset(const Offset(10, 20));
expect(viewsController.offsets, equals(<int, Offset>{})); expect(viewsController.offsets, equals(<int, Offset>{}));
}); });
test('synchronizeToNativeViewHierarchy', () async {
await PlatformViewsService.synchronizeToNativeViewHierarchy(false);
expect(viewsController.synchronizeToNativeViewHierarchy, false);
});
}); });
group('iOS', () { group('iOS', () {
......
...@@ -2312,6 +2312,43 @@ void main() { ...@@ -2312,6 +2312,43 @@ void main() {
expect(factoryInvocationCount, 1); expect(factoryInvocationCount, 1);
}); });
testWidgets(
'PlatformViewLink Widget init, should create a SizedBox widget before onPlatformViewCreated and a PlatformViewSurface after',
(WidgetTester tester) async {
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
late int createdPlatformViewId;
late PlatformViewCreatedCallback onPlatformViewCreatedCallBack;
final PlatformViewLink platformViewLink = PlatformViewLink(
viewType: 'webview',
onCreatePlatformView: (PlatformViewCreationParams params) {
onPlatformViewCreatedCallBack = params.onPlatformViewCreated;
createdPlatformViewId = params.id;
return FakePlatformViewController(params.id);
},
surfaceFactory: (BuildContext context, PlatformViewController controller) {
return PlatformViewSurface(
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
controller: controller,
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
);
},
);
await tester.pumpWidget(platformViewLink);
expect(() => tester.allWidgets.whereType<SizedBox>().first, returnsNormally);
onPlatformViewCreatedCallBack(createdPlatformViewId);
await tester.pump();
expect(() => tester.allWidgets.whereType<PlatformViewSurface>().first, returnsNormally);
expect(createdPlatformViewId, currentViewId + 1);
},
);
testWidgets('PlatformViewLink Widget dispose', (WidgetTester tester) async { testWidgets('PlatformViewLink Widget dispose', (WidgetTester tester) async {
late FakePlatformViewController disposedController; late FakePlatformViewController disposedController;
final PlatformViewLink platformViewLink = PlatformViewLink( final PlatformViewLink platformViewLink = PlatformViewLink(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment