Add viewType to PlatformViewLink (#39446)

* Add viewType to PlatformViewLink

Re-initialize the controller when the viewType changes.

* Re-word `PlatformViewLink` doc comment for clarity
This commit is contained in:
Harry Terkelsen 2019-08-28 20:02:08 -07:00 committed by GitHub
parent 4984d1a33d
commit 9f4ab273f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 135 additions and 36 deletions

View file

@ -588,6 +588,7 @@ class PlatformViewCreationParams {
const PlatformViewCreationParams._({
@required this.id,
@required this.viewType,
@required this.onPlatformViewCreated,
@required this.onFocusChanged,
}) : assert(id != null),
@ -598,6 +599,12 @@ class PlatformViewCreationParams {
/// [PlatformViewController.viewId] should match this id.
final int id;
/// The unique identifier for the type of platform view to be embedded.
///
/// This viewType is used to tell the platform which type of view to
/// associate with the [id].
final String viewType;
/// Callback invoked after the platform view has been created.
final PlatformViewCreatedCallback onPlatformViewCreated;
@ -637,6 +644,7 @@ typedef CreatePlatformViewCallback = PlatformViewController Function(PlatformVie
/// @override
/// Widget build(BuildContext context) {
/// return PlatformViewLink(
/// viewType: 'webview',
/// onCreatePlatformView: createFooWebView,
/// surfaceFactory: (BuildContext context, PlatformViewController controller) {
/// return PlatformViewSurface(
@ -650,8 +658,8 @@ typedef CreatePlatformViewCallback = PlatformViewController Function(PlatformVie
/// }
/// ```
///
/// The `surfaceFactory` and the `onCreatePlatformView` only take affect when the state of this widget is initialized.
/// If the widget is rebuilt without losing its state, `surfaceFactory` and `onCreatePlatformView` are ignored.
/// The `surfaceFactory` and the `onCreatePlatformView` are only called when the
/// state of this widget is initialized, or when the `viewType` changes.
class PlatformViewLink extends StatefulWidget {
/// Construct a [PlatformViewLink] widget.
@ -665,16 +673,23 @@ class PlatformViewLink extends StatefulWidget {
Key key,
@required PlatformViewSurfaceFactory surfaceFactory,
@required CreatePlatformViewCallback onCreatePlatformView,
@required this.viewType,
}) : assert(surfaceFactory != null),
assert(onCreatePlatformView != null),
_surfaceFactory = surfaceFactory,
_onCreatePlatformView = onCreatePlatformView,
super(key: key);
assert(onCreatePlatformView != null),
assert(viewType != null),
_surfaceFactory = surfaceFactory,
_onCreatePlatformView = onCreatePlatformView,
super(key: key);
final PlatformViewSurfaceFactory _surfaceFactory;
final CreatePlatformViewCallback _onCreatePlatformView;
/// The unique identifier for the view type to be embedded.
///
/// Typically, this viewType has already been registered on the platform side.
final String viewType;
@override
State<StatefulWidget> createState() => _PlatformViewLinkState();
}
@ -707,19 +722,33 @@ class _PlatformViewLinkState extends State<PlatformViewLink> {
super.initState();
}
@override
void didUpdateWidget(PlatformViewLink oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.viewType != oldWidget.viewType) {
_controller?.dispose();
// We are about to create a new platform view.
_platformViewCreated = false;
_initialize();
}
}
void _initialize() {
_id = platformViewsRegistry.getNextPlatformViewId();
_controller = widget._onCreatePlatformView(
PlatformViewCreationParams._(
id:_id,
onPlatformViewCreated:_onPlatformViewCreated,
onFocusChanged:_handlePlatformFocusChanged
id: _id,
viewType: widget.viewType,
onPlatformViewCreated: _onPlatformViewCreated,
onFocusChanged: _handlePlatformFocusChanged,
),
);
}
void _onPlatformViewCreated(int id) {
setState(() => _platformViewCreated = true);
setState(() { _platformViewCreated = true; });
}
void _handleFrameworkFocusChanged(bool isFocused) {

View file

@ -1939,16 +1939,19 @@ void main() {
PlatformViewCreatedCallback onPlatformViewCreatedCallBack;
final PlatformViewLink platformViewLink = PlatformViewLink(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,
);
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);
@ -1967,16 +1970,19 @@ void main() {
testWidgets('PlatformViewLink Widget dispose', (WidgetTester tester) async {
FakePlatformViewController disposedController;
final PlatformViewLink platformViewLink = PlatformViewLink(onCreatePlatformView: (PlatformViewCreationParams params){
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,
);
final PlatformViewLink platformViewLink = PlatformViewLink(
viewType: 'webview',
onCreatePlatformView: (PlatformViewCreationParams params){
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);
@ -1996,6 +2002,7 @@ void main() {
PlatformViewLink createPlatformViewLink() {
return PlatformViewLink(
key: key,
viewType: 'webview',
onCreatePlatformView: (PlatformViewCreationParams params){
ids.add(params.id);
controller = FakePlatformViewController(params.id);
@ -2041,13 +2048,75 @@ void main() {
);
});
testWidgets('PlatformViewLink re-initializes when view type changes', (WidgetTester tester) async {
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
final List<int> ids = <int>[];
final List<String> viewTypes = <String>[];
PlatformViewLink createPlatformViewLink(String viewType) {
return PlatformViewLink(
viewType: viewType,
onCreatePlatformView: (PlatformViewCreationParams params){
ids.add(params.id);
viewTypes.add(params.viewType);
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('webview'),
),
),
);
await tester.pumpWidget(
Center(
child: SizedBox(
width: 200.0,
height: 100.0,
child: createPlatformViewLink('maps'),
),
),
);
expect(
ids,
unorderedEquals(<int>[
currentViewId+1, currentViewId+2,
]),
);
expect(
viewTypes,
unorderedEquals(<String>[
'webview', 'maps',
]),
);
});
testWidgets('PlatformViewLink can take any widget to return in the SurfaceFactory', (WidgetTester tester) async {
final PlatformViewLink platformViewLink = PlatformViewLink(onCreatePlatformView: (PlatformViewCreationParams params){
params.onPlatformViewCreated(params.id);
return FakePlatformViewController(params.id);
}, surfaceFactory: (BuildContext context,PlatformViewController controller) {
return Container();
});
final PlatformViewLink platformViewLink = PlatformViewLink(
viewType: 'webview',
onCreatePlatformView: (PlatformViewCreationParams params){
params.onPlatformViewCreated(params.id);
return FakePlatformViewController(params.id);
},
surfaceFactory: (BuildContext context,PlatformViewController controller) {
return Container();
});
await tester.pumpWidget(platformViewLink);
@ -2062,6 +2131,7 @@ void main() {
FakePlatformViewController controller;
ValueChanged<bool> focusChanged;
final PlatformViewLink platformViewLink = PlatformViewLink(
viewType: 'webview',
onCreatePlatformView: (PlatformViewCreationParams params){
params.onPlatformViewCreated(params.id);
focusChanged = params.onFocusChanged;