PlatformViewLink, handling creation of the PlatformViewSurface and dispose PlatformViewController (#37703)
* link * review fixes * review fixes * remove extra line
This commit is contained in:
parent
07197e91c3
commit
5acf63d35a
@ -729,4 +729,9 @@ abstract class PlatformViewController {
|
||||
|
||||
/// Dispatches the `event` to the platform view.
|
||||
void dispatchPointerEvent(PointerEvent event);
|
||||
|
||||
/// Disposes the platform view.
|
||||
///
|
||||
/// The [PlatformViewController] is unusable after calling dispose.
|
||||
void dispose();
|
||||
}
|
||||
|
@ -581,6 +581,136 @@ class _UiKitPlatformView extends LeafRenderObjectWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// The parameters used to create a [PlatformViewController].
|
||||
///
|
||||
/// See also [CreatePlatformViewController] which uses this object to create a [PlatformViewController].
|
||||
class PlatformViewCreationParams {
|
||||
|
||||
const PlatformViewCreationParams._({
|
||||
@required this.id,
|
||||
@required this.onPlatformViewCreated
|
||||
}) : assert(id != null),
|
||||
assert(onPlatformViewCreated != null);
|
||||
|
||||
/// The unique identifier for the new platform view.
|
||||
///
|
||||
/// [PlatformViewController.viewId] should match this id.
|
||||
final int id;
|
||||
|
||||
/// Callback invoked after the platform view has been created.
|
||||
final PlatformViewCreatedCallback onPlatformViewCreated;
|
||||
}
|
||||
|
||||
/// A factory for a surface presenting a platform view as part of the widget hierarchy.
|
||||
///
|
||||
/// The returned widget should present the platform view associated with `controller`.
|
||||
///
|
||||
/// See also:
|
||||
/// * [PlatformViewSurface], a common widget for presenting platform views.
|
||||
typedef PlatformViewSurfaceFactory = Widget Function(BuildContext context, PlatformViewController controller);
|
||||
|
||||
/// Constructs a [PlatformViewController].
|
||||
///
|
||||
/// The [PlatformViewController.id] field of the created controller must match the value of the
|
||||
/// params [PlatformViewCreationParams.id] field.
|
||||
///
|
||||
/// See also [PlatformViewLink.onCreate].
|
||||
typedef CreatePlatformViewController = PlatformViewController Function(PlatformViewCreationParams params);
|
||||
|
||||
/// Links a platform view with the Flutter framework.
|
||||
///
|
||||
/// Provides common functionality for embedding a platform view (e.g an android.view.View on Android)
|
||||
/// with the Flutter framework.
|
||||
///
|
||||
/// {@macro flutter.widgets.platformViews.lifetime}
|
||||
///
|
||||
/// To implement a new platform view widget, return this widget in the `build` method.
|
||||
/// For example:
|
||||
/// ```dart
|
||||
/// class FooPlatformView extends StatelessWidget {
|
||||
/// @override
|
||||
/// Widget build(BuildContext context) {
|
||||
/// return PlatformViewLink(
|
||||
/// createCallback: createFooWebView,
|
||||
/// surfaceFactory: (BuildContext context, PlatformViewController controller) {
|
||||
/// return PlatformViewSurface(
|
||||
/// gestureRecognizers: gestureRecognizers,
|
||||
/// controller: controller,
|
||||
/// hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
||||
/// );
|
||||
/// },
|
||||
/// );
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The `surfaceFactory` and the `createPlatformViewController` only take affect when the state of this widget is initialized.
|
||||
/// If the widget is rebuilt without losing its state, `surfaceFactory` and `createPlatformViewController` are ignored.
|
||||
class PlatformViewLink extends StatefulWidget {
|
||||
|
||||
/// Construct a [PlatformViewLink] widget.
|
||||
///
|
||||
/// The `surfaceFactory` and the `createPlatformViewController` must not be null.
|
||||
///
|
||||
/// See also:
|
||||
/// * [PlatformViewSurface] for details on the widget returned by `surfaceFactory`.
|
||||
/// * [PlatformViewCreationParams] for how each parameter can be used when implementing `createPlatformView`.
|
||||
const PlatformViewLink({
|
||||
Key key,
|
||||
@required PlatformViewSurfaceFactory surfaceFactory,
|
||||
@required CreatePlatformViewController createPlatformViewController,
|
||||
}) : assert(surfaceFactory != null),
|
||||
assert(createPlatformViewController != null),
|
||||
_surfaceFactory = surfaceFactory,
|
||||
_createPlatformViewController = createPlatformViewController,
|
||||
super(key: key);
|
||||
|
||||
|
||||
final PlatformViewSurfaceFactory _surfaceFactory;
|
||||
final CreatePlatformViewController _createPlatformViewController;
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _PlatformViewLinkState();
|
||||
}
|
||||
|
||||
class _PlatformViewLinkState extends State<PlatformViewLink> {
|
||||
|
||||
int _id;
|
||||
PlatformViewController _controller;
|
||||
bool _platformViewCreated = false;
|
||||
PlatformViewSurface _surface;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!_platformViewCreated) {
|
||||
return const SizedBox.expand();
|
||||
}
|
||||
_surface ??= widget._surfaceFactory(context, _controller);
|
||||
return _surface;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_initialize();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void _initialize() {
|
||||
_id = platformViewsRegistry.getNextPlatformViewId();
|
||||
_controller = widget._createPlatformViewController(PlatformViewCreationParams._(id:_id, onPlatformViewCreated:_onPlatformViewCreated));
|
||||
}
|
||||
|
||||
void _onPlatformViewCreated(int id) {
|
||||
setState(() => _platformViewCreated = true);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// Integrates a platform view with Flutter's compositor, touch, and semantics subsystems.
|
||||
///
|
||||
/// The compositor integration is done by adding a [PlatformViewLayer] to the layer tree. [PlatformViewLayer]
|
||||
|
@ -17,6 +17,8 @@ class FakePlatformViewController extends PlatformViewController {
|
||||
_id = id;
|
||||
}
|
||||
|
||||
bool disposed = false;
|
||||
|
||||
/// Events that are dispatched;
|
||||
List<PointerEvent> dispatchedPointerEvents = <PointerEvent>[];
|
||||
|
||||
@ -32,6 +34,12 @@ class FakePlatformViewController extends PlatformViewController {
|
||||
|
||||
void clearTestingVariables() {
|
||||
dispatchedPointerEvents.clear();
|
||||
disposed = false;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1932,5 +1932,114 @@ void main() {
|
||||
);
|
||||
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();
|
||||
int createdPlatformViewId;
|
||||
|
||||
PlatformViewCreatedCallback onPlatformViewCreatedCallBack;
|
||||
|
||||
final PlatformViewLink platformViewLink = PlatformViewLink(createPlatformViewController: (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);
|
||||
final SizedBox sizedBox = tester.allWidgets.firstWhere((Widget widget) => widget is SizedBox);
|
||||
expect(sizedBox, isNotNull);
|
||||
|
||||
onPlatformViewCreatedCallBack(createdPlatformViewId);
|
||||
|
||||
await tester.pump();
|
||||
|
||||
final PlatformViewSurface surface = tester.allWidgets.firstWhere((Widget widget) => widget is PlatformViewSurface);
|
||||
expect(surface, isNotNull);
|
||||
|
||||
expect(createdPlatformViewId, currentViewId+1);
|
||||
});
|
||||
|
||||
testWidgets('PlatformViewLink Widget dispose', (WidgetTester tester) async {
|
||||
FakePlatformViewController disposedController;
|
||||
final PlatformViewLink platformViewLink = PlatformViewLink(createPlatformViewController: (PlatformViewCreationParams params){
|
||||
params.onPlatformViewCreated(params.id);
|
||||
disposedController = FakePlatformViewController(params.id);
|
||||
params.onPlatformViewCreated(params.id);
|
||||
return disposedController;
|
||||
}, surfaceFactory: (BuildContext context,PlatformViewController controller) {
|
||||
return PlatformViewSurface(
|
||||
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
|
||||
controller: controller,
|
||||
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
||||
);
|
||||
});
|
||||
|
||||
await tester.pumpWidget(platformViewLink);
|
||||
|
||||
await tester.pumpWidget(Container());
|
||||
|
||||
expect(disposedController.disposed, true);
|
||||
});
|
||||
|
||||
testWidgets('PlatformViewLink widget survives widget tree change', (WidgetTester tester) async {
|
||||
final GlobalKey key = GlobalKey();
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
final List<int> ids = <int>[];
|
||||
|
||||
FakePlatformViewController controller;
|
||||
|
||||
PlatformViewLink createPlatformViewLink() {
|
||||
return PlatformViewLink(
|
||||
key: key,
|
||||
createPlatformViewController: (PlatformViewCreationParams params){
|
||||
ids.add(params.id);
|
||||
controller = FakePlatformViewController(params.id);
|
||||
params.onPlatformViewCreated(params.id);
|
||||
return controller;
|
||||
},
|
||||
surfaceFactory: (BuildContext context, PlatformViewController controller) {
|
||||
return PlatformViewSurface(
|
||||
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
|
||||
controller: controller,
|
||||
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
await tester.pumpWidget(
|
||||
Center(
|
||||
child: SizedBox(
|
||||
width: 200.0,
|
||||
height: 100.0,
|
||||
child: createPlatformViewLink(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Center(
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
width: 200.0,
|
||||
height: 100.0,
|
||||
child: createPlatformViewLink(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(
|
||||
ids,
|
||||
unorderedEquals(<int>[
|
||||
currentViewId+1,
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user