mirror of
https://github.com/flutter/flutter
synced 2024-11-05 18:37:51 +00:00
Add no-op callbacks to platform view gesture recognizer when necessary (#61671)
After #31935, Some one sequence gesture recognizers requires at least one callback to be able to compete in the arena. This PR adds the a no-op callback in the gesture recognizer in the platform view when the gesture recognizer does not have any callbacks. This way, all the gesture recognizers in the platform view can compete in the arena.
This commit is contained in:
parent
99ef90472a
commit
30e556ddc5
2 changed files with 207 additions and 12 deletions
|
@ -401,7 +401,19 @@ class _UiKitViewGestureRecognizer extends OneSequenceGestureRecognizer {
|
|||
team.captain = this;
|
||||
_gestureRecognizers = gestureRecognizerFactories.map(
|
||||
(Factory<OneSequenceGestureRecognizer> recognizerFactory) {
|
||||
return recognizerFactory.constructor()..team = team;
|
||||
final OneSequenceGestureRecognizer gestureRecognizer = recognizerFactory.constructor();
|
||||
gestureRecognizer.team = team;
|
||||
// The below gesture recognizers requires at least one non-empty callback to
|
||||
// compete in the gesture arena.
|
||||
// https://github.com/flutter/flutter/issues/35394#issuecomment-562285087
|
||||
if (gestureRecognizer is LongPressGestureRecognizer) {
|
||||
gestureRecognizer.onLongPress ??= (){};
|
||||
} else if (gestureRecognizer is DragGestureRecognizer) {
|
||||
gestureRecognizer.onDown ??= (_){};
|
||||
} else if (gestureRecognizer is TapGestureRecognizer) {
|
||||
gestureRecognizer.onTapDown ??= (_){};
|
||||
}
|
||||
return gestureRecognizer;
|
||||
},
|
||||
).toSet();
|
||||
}
|
||||
|
@ -467,7 +479,19 @@ class _PlatformViewGestureRecognizer extends OneSequenceGestureRecognizer {
|
|||
team.captain = this;
|
||||
_gestureRecognizers = gestureRecognizerFactories.map(
|
||||
(Factory<OneSequenceGestureRecognizer> recognizerFactory) {
|
||||
return recognizerFactory.constructor()..team = team;
|
||||
final OneSequenceGestureRecognizer gestureRecognizer = recognizerFactory.constructor();
|
||||
gestureRecognizer.team = team;
|
||||
// The below gesture recognizers requires at least one non-empty callback to
|
||||
// compete in the gesture arena.
|
||||
// https://github.com/flutter/flutter/issues/35394#issuecomment-562285087
|
||||
if (gestureRecognizer is LongPressGestureRecognizer) {
|
||||
gestureRecognizer.onLongPress ??= (){};
|
||||
} else if (gestureRecognizer is DragGestureRecognizer) {
|
||||
gestureRecognizer.onDown ??= (_){};
|
||||
} else if (gestureRecognizer is TapGestureRecognizer) {
|
||||
gestureRecognizer.onTapDown ??= (_){};
|
||||
}
|
||||
return gestureRecognizer;
|
||||
},
|
||||
).toSet();
|
||||
_handlePointerEvent = handlePointerEvent;
|
||||
|
|
|
@ -576,7 +576,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('Android view gesture recognizers', (WidgetTester tester) async {
|
||||
testWidgets('Android view drag gesture recognizer', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
||||
viewsController.registerViewType('webview');
|
||||
|
@ -596,8 +596,7 @@ void main() {
|
|||
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
||||
Factory<VerticalDragGestureRecognizer>(
|
||||
() {
|
||||
return VerticalDragGestureRecognizer()
|
||||
..onStart = (_) {}; // Add callback to enable recognizer
|
||||
return VerticalDragGestureRecognizer();
|
||||
},
|
||||
),
|
||||
},
|
||||
|
@ -626,6 +625,96 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('Android view long press gesture recognizer', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
||||
viewsController.registerViewType('webview');
|
||||
bool longPressAccessedByParent = false;
|
||||
await tester.pumpWidget(
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: GestureDetector(
|
||||
onLongPress: () {
|
||||
longPressAccessedByParent = true;
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 200.0,
|
||||
height: 100.0,
|
||||
child: AndroidView(
|
||||
viewType: 'webview',
|
||||
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
||||
Factory<LongPressGestureRecognizer>(
|
||||
() {
|
||||
return LongPressGestureRecognizer();
|
||||
},
|
||||
),
|
||||
},
|
||||
layoutDirection: TextDirection.ltr,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.longPressAt(const Offset(50.0, 50.0));
|
||||
|
||||
expect(longPressAccessedByParent, false);
|
||||
expect(
|
||||
viewsController.motionEvents[currentViewId + 1],
|
||||
orderedEquals(<FakeAndroidMotionEvent>[
|
||||
const FakeAndroidMotionEvent(
|
||||
AndroidViewController.kActionDown, <int>[0], <Offset>[Offset(50.0, 50.0)]),
|
||||
const FakeAndroidMotionEvent(
|
||||
AndroidViewController.kActionUp, <int>[0], <Offset>[Offset(50.0, 50.0)]),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Android view tap gesture recognizer', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
||||
viewsController.registerViewType('webview');
|
||||
bool tapAccessedByParent = false;
|
||||
await tester.pumpWidget(
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
tapAccessedByParent = true;
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 200.0,
|
||||
height: 100.0,
|
||||
child: AndroidView(
|
||||
viewType: 'webview',
|
||||
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
||||
Factory<TapGestureRecognizer>(
|
||||
() {
|
||||
return TapGestureRecognizer();
|
||||
},
|
||||
),
|
||||
},
|
||||
layoutDirection: TextDirection.ltr,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.tapAt(const Offset(50.0, 50.0));
|
||||
|
||||
expect(tapAccessedByParent, false);
|
||||
expect(
|
||||
viewsController.motionEvents[currentViewId + 1],
|
||||
orderedEquals(<FakeAndroidMotionEvent>[
|
||||
const FakeAndroidMotionEvent(
|
||||
AndroidViewController.kActionDown, <int>[0], <Offset>[Offset(50.0, 50.0)]),
|
||||
const FakeAndroidMotionEvent(
|
||||
AndroidViewController.kActionUp, <int>[0], <Offset>[Offset(50.0, 50.0)]),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Android view can claim gesture after all pointers are up', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
||||
|
@ -1422,17 +1511,17 @@ void main() {
|
|||
expect(viewsController.gesturesRejected[currentViewId + 1], 1);
|
||||
});
|
||||
|
||||
testWidgets('UiKitView gesture recognizers', (WidgetTester tester) async {
|
||||
testWidgets('UiKitView tap gesture recognizers', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
||||
viewsController.registerViewType('webview');
|
||||
bool verticalDragAcceptedByParent = false;
|
||||
bool gestureAcceptedByParent = false;
|
||||
await tester.pumpWidget(
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: GestureDetector(
|
||||
onVerticalDragStart: (DragStartDetails d) {
|
||||
verticalDragAcceptedByParent = true;
|
||||
gestureAcceptedByParent = true;
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 200.0,
|
||||
|
@ -1442,8 +1531,7 @@ void main() {
|
|||
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
||||
Factory<VerticalDragGestureRecognizer>(
|
||||
() {
|
||||
return VerticalDragGestureRecognizer()
|
||||
..onStart = (_) {}; // Add callback to enable recognizer
|
||||
return VerticalDragGestureRecognizer();
|
||||
},
|
||||
),
|
||||
},
|
||||
|
@ -1462,6 +1550,90 @@ void main() {
|
|||
await gesture.moveBy(const Offset(0.0, 100.0));
|
||||
await gesture.up();
|
||||
|
||||
expect(gestureAcceptedByParent, false);
|
||||
expect(viewsController.gesturesAccepted[currentViewId + 1], 1);
|
||||
expect(viewsController.gesturesRejected[currentViewId + 1], 0);
|
||||
});
|
||||
|
||||
testWidgets('UiKitView long press gesture recognizers', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
||||
viewsController.registerViewType('webview');
|
||||
bool gestureAcceptedByParent = false;
|
||||
await tester.pumpWidget(
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: GestureDetector(
|
||||
onLongPress: () {
|
||||
gestureAcceptedByParent = true;
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 200.0,
|
||||
height: 100.0,
|
||||
child: UiKitView(
|
||||
viewType: 'webview',
|
||||
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
||||
Factory<LongPressGestureRecognizer>(
|
||||
() {
|
||||
return LongPressGestureRecognizer();
|
||||
},
|
||||
),
|
||||
},
|
||||
layoutDirection: TextDirection.ltr,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// First frame is before the platform view was created so the render object
|
||||
// is not yet in the tree.
|
||||
await tester.pump();
|
||||
|
||||
await tester.longPressAt(const Offset(50.0, 50.0));
|
||||
|
||||
expect(gestureAcceptedByParent, false);
|
||||
expect(viewsController.gesturesAccepted[currentViewId + 1], 1);
|
||||
expect(viewsController.gesturesRejected[currentViewId + 1], 0);
|
||||
});
|
||||
|
||||
testWidgets('UiKitView drag gesture recognizers', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
||||
viewsController.registerViewType('webview');
|
||||
bool verticalDragAcceptedByParent = false;
|
||||
await tester.pumpWidget(
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: GestureDetector(
|
||||
onVerticalDragStart: (DragStartDetails d) {
|
||||
verticalDragAcceptedByParent = true;
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 200.0,
|
||||
height: 100.0,
|
||||
child: UiKitView(
|
||||
viewType: 'webview',
|
||||
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
||||
Factory<TapGestureRecognizer>(
|
||||
() {
|
||||
return TapGestureRecognizer();
|
||||
},
|
||||
),
|
||||
},
|
||||
layoutDirection: TextDirection.ltr,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// First frame is before the platform view was created so the render object
|
||||
// is not yet in the tree.
|
||||
await tester.pump();
|
||||
|
||||
await tester.tapAt(const Offset(50.0, 50.0));
|
||||
|
||||
expect(verticalDragAcceptedByParent, false);
|
||||
expect(viewsController.gesturesAccepted[currentViewId + 1], 1);
|
||||
expect(viewsController.gesturesRejected[currentViewId + 1], 0);
|
||||
|
@ -1806,8 +1978,7 @@ void main() {
|
|||
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
||||
Factory<VerticalDragGestureRecognizer>(
|
||||
() {
|
||||
return VerticalDragGestureRecognizer()
|
||||
..onStart = (_) {}; // Add callback to enable recognizer
|
||||
return VerticalDragGestureRecognizer();
|
||||
},
|
||||
),
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue