Unverified Commit dcbc694b authored by Maurice Parrish's avatar Maurice Parrish Committed by GitHub

Have AndroidViewController extend PlatformViewController and add support for...

Have AndroidViewController extend PlatformViewController and add support for hybrid platform views (#60320)
parent 462b0ea7
......@@ -15,8 +15,8 @@ class AndroidPlatformView extends StatelessWidget {
const AndroidPlatformView({
Key key,
@required this.viewType,
}) : assert(viewType != null),
super(key: key);
}) : assert(viewType != null),
super(key: key);
/// The unique identifier for the view type to be embedded by this widget.
///
......@@ -27,61 +27,23 @@ class AndroidPlatformView extends StatelessWidget {
Widget build(BuildContext context) {
return PlatformViewLink(
viewType: viewType,
onCreatePlatformView: _onCreateAndroidView,
surfaceFactory: (BuildContext context, PlatformViewController controller) {
return PlatformViewSurface(
controller: controller,
surfaceFactory:
(BuildContext context, PlatformViewController controller) {
return AndroidViewSurface(
controller: controller as AndroidViewController,
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
);
},
onCreatePlatformView: (PlatformViewCreationParams params) {
return PlatformViewsService.initAndroidView(
id: params.id,
viewType: params.viewType,
layoutDirection: TextDirection.ltr,
)
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
..create();
},
);
}
PlatformViewController _onCreateAndroidView(PlatformViewCreationParams params) {
final _AndroidViewController controller = _AndroidViewController(params.id, viewType);
controller._initialize().then((_) { params.onPlatformViewCreated(params.id); });
return controller;
}
}
// TODO(egarciad): The Android view controller should be defined in the framework.
// https://github.com/flutter/flutter/issues/55904
class _AndroidViewController extends PlatformViewController {
_AndroidViewController(
this.viewId,
this.viewType,
);
@override
final int viewId;
/// The unique identifier for the Android view type to be embedded by this widget.
///
/// A PlatformViewFactory for this type must have been registered.
final String viewType;
bool _initialized = false;
Future<void> _initialize() async {
// TODO(egarciad): Initialize platform view.
_initialized = true;
}
@override
void clearFocus() {
// TODO(egarciad): Implement clear focus.
}
@override
void dispatchPointerEvent(PointerEvent event) {
// TODO(egarciad): Implement dispatchPointerEvent
}
@override
void dispose() {
if (_initialized) {
// TODO(egarciad): Dispose the android view.
}
}
}
......@@ -90,7 +90,7 @@ class RenderAndroidView extends RenderBox with _PlatformViewGestureMixin {
assert(hitTestBehavior != null),
assert(gestureRecognizers != null),
_viewController = viewController {
_motionEventsDispatcher = _MotionEventsDispatcher(globalToLocal, viewController);
_viewController.pointTransformer = (Offset offset) => globalToLocal(offset);
updateGestureRecognizers(gestureRecognizers);
_viewController.addOnPlatformViewCreatedListener(_onPlatformViewCreated);
this.hitTestBehavior = hitTestBehavior;
......@@ -139,7 +139,7 @@ class RenderAndroidView extends RenderBox with _PlatformViewGestureMixin {
/// 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, _motionEventsDispatcher.handlePointerEvent);
_updateGestureRecognizersWithCallBack(gestureRecognizers, _viewController.dispatchPointerEvent);
}
@override
......@@ -151,8 +151,6 @@ class RenderAndroidView extends RenderBox with _PlatformViewGestureMixin {
@override
bool get isRepaintBoundary => true;
_MotionEventsDispatcher _motionEventsDispatcher;
@override
void performResize() {
size = constraints.biggest;
......@@ -225,7 +223,7 @@ class RenderAndroidView extends RenderBox with _PlatformViewGestureMixin {
config.isSemanticBoundary = true;
if (_viewController.isCreated) {
config.platformViewId = _viewController.id;
config.platformViewId = _viewController.viewId;
}
}
}
......@@ -451,7 +449,7 @@ class _UiKitViewGestureRecognizer extends OneSequenceGestureRecognizer {
}
}
typedef _HandlePointerEvent = void Function(PointerEvent event);
typedef _HandlePointerEvent = Future<void> Function(PointerEvent event);
// This recognizer constructs gesture recognizers from a set of gesture recognizer factories
// it was give, adds all of them to a gesture arena team with the _PlatformViewGestureRecognizer
......@@ -555,144 +553,6 @@ class _PlatformViewGestureRecognizer extends OneSequenceGestureRecognizer {
}
}
typedef _GlobalToLocal = Offset Function(Offset point);
// Composes a stream of PointerEvent objects into AndroidMotionEvent objects
// and dispatches them to the associated embedded Android view.
class _MotionEventsDispatcher {
_MotionEventsDispatcher(this.globalToLocal, this.viewController);
final Map<int, AndroidPointerCoords> pointerPositions = <int, AndroidPointerCoords>{};
final Map<int, AndroidPointerProperties> pointerProperties = <int, AndroidPointerProperties>{};
final _GlobalToLocal globalToLocal;
final AndroidViewController viewController;
int nextPointerId = 0;
int downTimeMillis;
void handlePointerEvent(PointerEvent event) {
if (event is PointerDownEvent) {
if (nextPointerId == 0)
downTimeMillis = event.timeStamp.inMilliseconds;
pointerProperties[event.pointer] = propertiesFor(event, nextPointerId++);
}
pointerPositions[event.pointer] = coordsFor(event);
dispatchPointerEvent(event);
if (event is PointerUpEvent) {
pointerPositions.remove(event.pointer);
pointerProperties.remove(event.pointer);
if (pointerProperties.isEmpty) {
nextPointerId = 0;
downTimeMillis = null;
}
}
if (event is PointerCancelEvent) {
pointerPositions.clear();
pointerProperties.clear();
nextPointerId = 0;
downTimeMillis = null;
}
}
void dispatchPointerEvent(PointerEvent event) {
final List<int> pointers = pointerPositions.keys.toList();
final int pointerIdx = pointers.indexOf(event.pointer);
final int numPointers = pointers.length;
// This value must match the value in engine's FlutterView.java.
// This flag indicates whether the original Android pointer events were batched together.
const int kPointerDataFlagBatched = 1;
// Android MotionEvent objects can batch information on multiple pointers.
// Flutter breaks these such batched events into multiple PointerEvent objects.
// When there are multiple active pointers we accumulate the information for all pointers
// as we get PointerEvents, and only send it to the embedded Android view when
// we see the last pointer. This way we achieve the same batching as Android.
if (event.platformData == kPointerDataFlagBatched ||
(isSinglePointerAction(event) && pointerIdx < numPointers - 1))
return;
int action;
switch (event.runtimeType) {
case PointerDownEvent:
action = numPointers == 1 ? AndroidViewController.kActionDown
: AndroidViewController.pointerAction(pointerIdx, AndroidViewController.kActionPointerDown);
break;
case PointerUpEvent:
action = numPointers == 1 ? AndroidViewController.kActionUp
: AndroidViewController.pointerAction(pointerIdx, AndroidViewController.kActionPointerUp);
break;
case PointerMoveEvent:
action = AndroidViewController.kActionMove;
break;
case PointerCancelEvent:
action = AndroidViewController.kActionCancel;
break;
default:
return;
}
final AndroidMotionEvent androidMotionEvent = AndroidMotionEvent(
downTime: downTimeMillis,
eventTime: event.timeStamp.inMilliseconds,
action: action,
pointerCount: pointerPositions.length,
pointerProperties: pointers.map<AndroidPointerProperties>((int i) => pointerProperties[i]).toList(),
pointerCoords: pointers.map<AndroidPointerCoords>((int i) => pointerPositions[i]).toList(),
metaState: 0,
buttonState: 0,
xPrecision: 1.0,
yPrecision: 1.0,
deviceId: 0,
edgeFlags: 0,
source: 0,
flags: 0,
);
viewController.sendMotionEvent(androidMotionEvent);
}
AndroidPointerCoords coordsFor(PointerEvent event) {
final Offset position = globalToLocal(event.position);
return AndroidPointerCoords(
orientation: event.orientation,
pressure: event.pressure,
size: event.size,
toolMajor: event.radiusMajor,
toolMinor: event.radiusMinor,
touchMajor: event.radiusMajor,
touchMinor: event.radiusMinor,
x: position.dx,
y: position.dy,
);
}
AndroidPointerProperties propertiesFor(PointerEvent event, int pointerId) {
int toolType = AndroidPointerProperties.kToolTypeUnknown;
switch(event.kind) {
case PointerDeviceKind.touch:
toolType = AndroidPointerProperties.kToolTypeFinger;
break;
case PointerDeviceKind.mouse:
toolType = AndroidPointerProperties.kToolTypeMouse;
break;
case PointerDeviceKind.stylus:
toolType = AndroidPointerProperties.kToolTypeStylus;
break;
case PointerDeviceKind.invertedStylus:
toolType = AndroidPointerProperties.kToolTypeEraser;
break;
case PointerDeviceKind.unknown:
toolType = AndroidPointerProperties.kToolTypeUnknown;
break;
}
return AndroidPointerProperties(id: pointerId, toolType: toolType);
}
bool isSinglePointerAction(PointerEvent event) => event is! PointerDownEvent && event is! PointerUpEvent;
}
/// A render object for embedding a platform view.
///
/// [PlatformViewRenderBox] presents a platform view by adding a [PlatformViewLayer] layer,
......
......@@ -398,22 +398,21 @@ class _HtmlElementViewController extends PlatformViewController {
}
@override
void clearFocus() {
Future<void> clearFocus() async {
// Currently this does nothing on Flutter Web.
// TODO(het): Implement this. See https://github.com/flutter/flutter/issues/39496
}
@override
void dispatchPointerEvent(PointerEvent event) {
Future<void> dispatchPointerEvent(PointerEvent event) async {
// We do not dispatch pointer events to HTML views because they may contain
// cross-origin iframes, which only accept user-generated events.
}
@override
void dispose() {
Future<void> dispose() async {
if (_initialized) {
// Asynchronously dispose this view.
SystemChannels.platform_views.invokeMethod<void>('dispose', viewId);
await SystemChannels.platform_views.invokeMethod<void>('dispose', viewId);
}
}
}
......@@ -904,8 +903,9 @@ class _PlatformViewLinkState extends State<PlatformViewLink> {
/// 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]
/// isn't supported on all platforms (e.g on Android platform views are composited using a [TextureLayer]).
/// The compositor integration is done by adding a [PlatformViewLayer] to the layer tree. [PlatformViewSurface]
/// isn't supported on all platforms (e.g on Android platform views can be composited by using a [TextureLayer] or
/// [AndroidViewSurface]).
/// Custom Flutter embedders can support [PlatformViewLayer]s by implementing a SystemCompositor.
///
/// The widget fills all available space, the parent of this object must provide bounded layout
......@@ -915,7 +915,7 @@ class _PlatformViewLinkState extends State<PlatformViewLink> {
///
/// 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.
// TODO(amirh): Link to the embedder's system compositor documentation once available.
class PlatformViewSurface extends LeafRenderObjectWidget {
......@@ -996,3 +996,46 @@ class PlatformViewSurface extends LeafRenderObjectWidget {
..updateGestureRecognizers(gestureRecognizers);
}
}
/// Integrates an Android view with Flutter's compositor, touch, and semantics subsystems.
///
/// 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 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.
///
/// See also:
///
/// * [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.
class AndroidViewSurface extends PlatformViewSurface {
/// Construct an `AndroidPlatformViewSurface`.
const AndroidViewSurface({
Key key,
@required AndroidViewController controller,
@required PlatformViewHitTestBehavior hitTestBehavior,
@required Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
}) : assert(controller != null),
assert(hitTestBehavior != null),
assert(gestureRecognizers != null),
super(
key: key,
controller: controller,
hitTestBehavior: hitTestBehavior,
gestureRecognizers: gestureRecognizers);
@override
RenderObject createRenderObject(BuildContext context) {
final PlatformViewRenderBox renderBox =
super.createRenderObject(context) as PlatformViewRenderBox;
(controller as AndroidViewController).pointTransformer =
(Offset position) => renderBox.globalToLocal(position);
return renderBox;
}
}
......@@ -31,7 +31,7 @@ class FakePlatformViewController extends PlatformViewController {
int get viewId => _id;
@override
void dispatchPointerEvent(PointerEvent event) {
Future<void> dispatchPointerEvent(PointerEvent event) async {
dispatchedPointerEvents.add(event);
}
......@@ -42,16 +42,92 @@ class FakePlatformViewController extends PlatformViewController {
}
@override
void dispose() {
Future<void> dispose() async {
disposed = true;
}
@override
void clearFocus() {
Future<void> clearFocus() async {
focusCleared = true;
}
}
class FakeAndroidViewController implements AndroidViewController {
FakeAndroidViewController(this.viewId);
bool disposed = false;
bool focusCleared = false;
bool created = false;
/// Events that are dispatched;
List<PointerEvent> dispatchedPointerEvents = <PointerEvent>[];
@override
final int viewId;
@override
Offset Function(Offset position) pointTransformer;
@override
Future<void> dispatchPointerEvent(PointerEvent event) async {
dispatchedPointerEvents.add(event);
}
void clearTestingVariables() {
dispatchedPointerEvents.clear();
disposed = false;
focusCleared = false;
}
@override
Future<void> dispose() async {
disposed = true;
}
@override
Future<void> clearFocus() async {
focusCleared = true;
}
@override
Future<void> setSize(Size size) {
throw UnimplementedError();
}
@override
int get textureId => throw UnimplementedError();
@override
bool isCreated;
@override
void addOnPlatformViewCreatedListener(PlatformViewCreatedCallback listener) =>
throw UnimplementedError();
@override
int get id => throw UnimplementedError();
@override
void removeOnPlatformViewCreatedListener(PlatformViewCreatedCallback listener) {
throw UnimplementedError();
}
@override
Future<void> sendMotionEvent(AndroidMotionEvent event) {
throw UnimplementedError();
}
@override
Future<void> setLayoutDirection(TextDirection layoutDirection) {
throw UnimplementedError();
}
@override
Future<void> create() async {
created = true;
}
}
class FakeAndroidPlatformViewsController {
FakeAndroidPlatformViewsController() {
SystemChannels.platform_views.setMockMethodCallHandler(_onMethodCall);
......@@ -108,6 +184,7 @@ class FakeAndroidPlatformViewsController {
final double width = args['width'] as double;
final double height = args['height'] as double;
final int layoutDirection = args['direction'] as int;
final bool hybrid = args['hybrid'] as bool;
final Uint8List creationParams = args['params'] as Uint8List;
if (_views.containsKey(id))
......@@ -126,13 +203,23 @@ class FakeAndroidPlatformViewsController {
await createCompleter.future;
}
_views[id] = FakeAndroidPlatformView(id, viewType, Size(width, height), layoutDirection, creationParams);
_views[id] = FakeAndroidPlatformView(id, viewType,
width != null || height != null ? Size(width, height) : null,
layoutDirection,
hybrid,
creationParams,
);
final int textureId = _textureCounter++;
return Future<int>.sync(() => textureId);
}
Future<dynamic> _dispose(MethodCall call) {
final int id = call.arguments as int;
int id;
if (call.arguments is int) {
id = call.arguments as int;
} else if (call.arguments is Map && call.arguments['hybrid'] == true) {
id = call.arguments['id'] as int;
}
if (!_views.containsKey(id))
throw PlatformException(
......@@ -381,19 +468,21 @@ class FakeHtmlPlatformViewsController {
@immutable
class FakeAndroidPlatformView {
const FakeAndroidPlatformView(this.id, this.type, this.size, this.layoutDirection, [this.creationParams]);
const FakeAndroidPlatformView(this.id, this.type, this.size, this.layoutDirection, this.hybrid, [this.creationParams]);
final int id;
final String type;
final Uint8List creationParams;
final Size size;
final int layoutDirection;
final bool hybrid;
FakeAndroidPlatformView copyWith({Size size, int layoutDirection}) => FakeAndroidPlatformView(
id,
type,
size ?? this.size,
layoutDirection ?? this.layoutDirection,
hybrid,
creationParams,
);
......@@ -406,15 +495,16 @@ class FakeAndroidPlatformView {
&& other.type == type
&& listEquals<int>(other.creationParams, creationParams)
&& other.size == size
&& other.hybrid == hybrid
&& other.layoutDirection == layoutDirection;
}
@override
int get hashCode => hashValues(id, type, hashList(creationParams), size, layoutDirection);
int get hashCode => hashValues(id, type, hashList(creationParams), size, layoutDirection, hybrid);
@override
String toString() {
return 'FakeAndroidPlatformView(id: $id, type: $type, size: $size, layoutDirection: $layoutDirection, creationParams: $creationParams)';
return 'FakeAndroidPlatformView(id: $id, type: $type, size: $size, layoutDirection: $layoutDirection, hybrid: $hybrid, creationParams: $creationParams)';
}
}
......
......@@ -31,6 +31,17 @@ void main() {
},
throwsA(isA<PlatformException>()),
);
expect(
() {
return PlatformViewsService.initSurfaceAndroidView(
id: 0,
viewType: 'web',
layoutDirection: TextDirection.ltr,
).create();
},
throwsA(isA<PlatformException>()),
);
});
test('create Android views', () async {
......@@ -39,11 +50,13 @@ void main() {
.setSize(const Size(100.0, 100.0));
await PlatformViewsService.initAndroidView( id: 1, viewType: 'webview', layoutDirection: TextDirection.rtl)
.setSize(const Size(200.0, 300.0));
await PlatformViewsService.initSurfaceAndroidView(id: 2, viewType: 'webview', layoutDirection: TextDirection.rtl).create();
expect(
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
const FakeAndroidPlatformView(0, 'webview', Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr),
const FakeAndroidPlatformView(1, 'webview', Size(200.0, 300.0), AndroidViewController.kAndroidLayoutDirectionRtl),
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(2, 'webview', null, AndroidViewController.kAndroidLayoutDirectionRtl, true),
]));
});
......@@ -58,6 +71,16 @@ void main() {
() => PlatformViewsService.initAndroidView(
id: 0, viewType: 'web', layoutDirection: TextDirection.ltr).setSize(const Size(100.0, 100.0)),
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 {
......@@ -67,12 +90,16 @@ void main() {
final AndroidViewController viewController =
PlatformViewsService.initAndroidView(id: 1, viewType: 'webview', layoutDirection: TextDirection.ltr);
await viewController.setSize(const Size(200.0, 300.0));
await viewController.dispose();
final AndroidViewController surfaceViewController = PlatformViewsService.initSurfaceAndroidView(id: 1, viewType: 'webview', layoutDirection: TextDirection.ltr);
await surfaceViewController.create();
await surfaceViewController.dispose();
expect(
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
const FakeAndroidPlatformView(0, 'webview', Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr),
const FakeAndroidPlatformView(0, 'webview', Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr, null),
]));
});
......@@ -115,8 +142,8 @@ void main() {
expect(
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
const FakeAndroidPlatformView(0, 'webview', Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr),
const FakeAndroidPlatformView(1, 'webview', Size(500.0, 500.0), AndroidViewController.kAndroidLayoutDirectionLtr),
const FakeAndroidPlatformView(0, 'webview', Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr, null),
const FakeAndroidPlatformView(1, 'webview', Size(500.0, 500.0), AndroidViewController.kAndroidLayoutDirectionLtr, null),
]));
});
......@@ -156,7 +183,7 @@ void main() {
expect(
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
const FakeAndroidPlatformView(0, 'webview', Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr),
const FakeAndroidPlatformView(0, 'webview', Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr, null),
]));
});
......@@ -169,7 +196,7 @@ void main() {
expect(
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
const FakeAndroidPlatformView(0, 'webview', Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionRtl),
const FakeAndroidPlatformView(0, 'webview', Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionRtl, null),
]));
});
});
......
......@@ -39,7 +39,7 @@ void main() {
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
FakeAndroidPlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0),
AndroidViewController.kAndroidLayoutDirectionLtr),
AndroidViewController.kAndroidLayoutDirectionLtr, null),
]),
);
});
......@@ -78,7 +78,7 @@ void main() {
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
FakeAndroidPlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0),
AndroidViewController.kAndroidLayoutDirectionLtr, fakeView.creationParams),
AndroidViewController.kAndroidLayoutDirectionLtr, null, fakeView.creationParams),
]),
);
});
......@@ -137,7 +137,7 @@ void main() {
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
FakeAndroidPlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0),
AndroidViewController.kAndroidLayoutDirectionLtr),
AndroidViewController.kAndroidLayoutDirectionLtr, null),
]),
);
......@@ -148,7 +148,7 @@ void main() {
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
FakeAndroidPlatformView(currentViewId + 1, 'webview', const Size(100.0, 50.0),
AndroidViewController.kAndroidLayoutDirectionLtr),
AndroidViewController.kAndroidLayoutDirectionLtr, null),
]),
);
});
......@@ -182,7 +182,7 @@ void main() {
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
FakeAndroidPlatformView(currentViewId + 2, 'maps', const Size(200.0, 100.0),
AndroidViewController.kAndroidLayoutDirectionLtr),
AndroidViewController.kAndroidLayoutDirectionLtr, null),
]),
);
});
......@@ -246,7 +246,7 @@ void main() {
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
FakeAndroidPlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0),
AndroidViewController.kAndroidLayoutDirectionLtr),
AndroidViewController.kAndroidLayoutDirectionLtr, null),
]),
);
});
......@@ -471,7 +471,7 @@ void main() {
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
FakeAndroidPlatformView(currentViewId + 1, 'maps', const Size(200.0, 100.0),
AndroidViewController.kAndroidLayoutDirectionRtl),
AndroidViewController.kAndroidLayoutDirectionRtl, null),
]),
);
......@@ -489,7 +489,7 @@ void main() {
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
FakeAndroidPlatformView(currentViewId + 1, 'maps', const Size(200.0, 100.0),
AndroidViewController.kAndroidLayoutDirectionLtr),
AndroidViewController.kAndroidLayoutDirectionLtr, null),
]),
);
});
......@@ -515,7 +515,7 @@ void main() {
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
FakeAndroidPlatformView(currentViewId + 1, 'maps', const Size(200.0, 100.0),
AndroidViewController.kAndroidLayoutDirectionRtl),
AndroidViewController.kAndroidLayoutDirectionRtl, null),
]),
);
......@@ -536,7 +536,7 @@ void main() {
viewsController.views,
unorderedEquals(<FakeAndroidPlatformView>[
FakeAndroidPlatformView(currentViewId + 1, 'maps', const Size(200.0, 100.0),
AndroidViewController.kAndroidLayoutDirectionLtr),
AndroidViewController.kAndroidLayoutDirectionLtr, null),
]),
);
});
......@@ -1016,6 +1016,23 @@ void main() {
});
});
group('AndroidViewSurface', () {
FakeAndroidViewController controller;
setUp(() {
controller = FakeAndroidViewController(0);
});
testWidgets('AndroidViewSurface sets pointTransformer of view controller', (WidgetTester tester) async {
final AndroidViewSurface surface = AndroidViewSurface(
controller: controller,
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},);
await tester.pumpWidget(surface);
expect(controller.pointTransformer, isNotNull);
});
});
group('UiKitView', () {
testWidgets('Create UIView', (WidgetTester tester) async {
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
......
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