Skip to content

Commit 7b07b85

Browse files
authored
Add supportedDevices parameter to GestureDetector (#107312)
1 parent 22f51c3 commit 7b07b85

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

packages/flutter/lib/src/widgets/gesture_detector.dart

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ class GestureDetector extends StatelessWidget {
288288
this.behavior,
289289
this.excludeFromSemantics = false,
290290
this.dragStartBehavior = DragStartBehavior.start,
291+
this.supportedDevices,
291292
}) : assert(excludeFromSemantics != null),
292293
assert(dragStartBehavior != null),
293294
assert(() {
@@ -1004,6 +1005,11 @@ class GestureDetector extends StatelessWidget {
10041005
/// * [DragGestureRecognizer.dragStartBehavior], which gives an example for the different behaviors.
10051006
final DragStartBehavior dragStartBehavior;
10061007

1008+
/// The kind of devices that are allowed to be recognized.
1009+
///
1010+
/// If set to null, events from all device types will be recognized. Defaults to null.
1011+
final Set<PointerDeviceKind>? supportedDevices;
1012+
10071013
@override
10081014
Widget build(BuildContext context) {
10091015
final Map<Type, GestureRecognizerFactory> gestures = <Type, GestureRecognizerFactory>{};
@@ -1022,7 +1028,7 @@ class GestureDetector extends StatelessWidget {
10221028
onTertiaryTapCancel != null
10231029
) {
10241030
gestures[TapGestureRecognizer] = GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
1025-
() => TapGestureRecognizer(debugOwner: this),
1031+
() => TapGestureRecognizer(debugOwner: this, supportedDevices: supportedDevices),
10261032
(TapGestureRecognizer instance) {
10271033
instance
10281034
..onTapDown = onTapDown
@@ -1043,7 +1049,7 @@ class GestureDetector extends StatelessWidget {
10431049

10441050
if (onDoubleTap != null) {
10451051
gestures[DoubleTapGestureRecognizer] = GestureRecognizerFactoryWithHandlers<DoubleTapGestureRecognizer>(
1046-
() => DoubleTapGestureRecognizer(debugOwner: this),
1052+
() => DoubleTapGestureRecognizer(debugOwner: this, supportedDevices: supportedDevices),
10471053
(DoubleTapGestureRecognizer instance) {
10481054
instance
10491055
..onDoubleTapDown = onDoubleTapDown
@@ -1076,7 +1082,7 @@ class GestureDetector extends StatelessWidget {
10761082
onTertiaryLongPressUp != null ||
10771083
onTertiaryLongPressEnd != null) {
10781084
gestures[LongPressGestureRecognizer] = GestureRecognizerFactoryWithHandlers<LongPressGestureRecognizer>(
1079-
() => LongPressGestureRecognizer(debugOwner: this),
1085+
() => LongPressGestureRecognizer(debugOwner: this, supportedDevices: supportedDevices),
10801086
(LongPressGestureRecognizer instance) {
10811087
instance
10821088
..onLongPressDown = onLongPressDown
@@ -1111,7 +1117,7 @@ class GestureDetector extends StatelessWidget {
11111117
onVerticalDragEnd != null ||
11121118
onVerticalDragCancel != null) {
11131119
gestures[VerticalDragGestureRecognizer] = GestureRecognizerFactoryWithHandlers<VerticalDragGestureRecognizer>(
1114-
() => VerticalDragGestureRecognizer(debugOwner: this),
1120+
() => VerticalDragGestureRecognizer(debugOwner: this, supportedDevices: supportedDevices),
11151121
(VerticalDragGestureRecognizer instance) {
11161122
instance
11171123
..onDown = onVerticalDragDown
@@ -1131,7 +1137,7 @@ class GestureDetector extends StatelessWidget {
11311137
onHorizontalDragEnd != null ||
11321138
onHorizontalDragCancel != null) {
11331139
gestures[HorizontalDragGestureRecognizer] = GestureRecognizerFactoryWithHandlers<HorizontalDragGestureRecognizer>(
1134-
() => HorizontalDragGestureRecognizer(debugOwner: this),
1140+
() => HorizontalDragGestureRecognizer(debugOwner: this, supportedDevices: supportedDevices),
11351141
(HorizontalDragGestureRecognizer instance) {
11361142
instance
11371143
..onDown = onHorizontalDragDown
@@ -1151,7 +1157,7 @@ class GestureDetector extends StatelessWidget {
11511157
onPanEnd != null ||
11521158
onPanCancel != null) {
11531159
gestures[PanGestureRecognizer] = GestureRecognizerFactoryWithHandlers<PanGestureRecognizer>(
1154-
() => PanGestureRecognizer(debugOwner: this),
1160+
() => PanGestureRecognizer(debugOwner: this, supportedDevices: supportedDevices),
11551161
(PanGestureRecognizer instance) {
11561162
instance
11571163
..onDown = onPanDown
@@ -1167,7 +1173,7 @@ class GestureDetector extends StatelessWidget {
11671173

11681174
if (onScaleStart != null || onScaleUpdate != null || onScaleEnd != null) {
11691175
gestures[ScaleGestureRecognizer] = GestureRecognizerFactoryWithHandlers<ScaleGestureRecognizer>(
1170-
() => ScaleGestureRecognizer(debugOwner: this),
1176+
() => ScaleGestureRecognizer(debugOwner: this, supportedDevices: supportedDevices),
11711177
(ScaleGestureRecognizer instance) {
11721178
instance
11731179
..onStart = onScaleStart
@@ -1184,7 +1190,7 @@ class GestureDetector extends StatelessWidget {
11841190
onForcePressUpdate != null ||
11851191
onForcePressEnd != null) {
11861192
gestures[ForcePressGestureRecognizer] = GestureRecognizerFactoryWithHandlers<ForcePressGestureRecognizer>(
1187-
() => ForcePressGestureRecognizer(debugOwner: this),
1193+
() => ForcePressGestureRecognizer(debugOwner: this, supportedDevices: supportedDevices),
11881194
(ForcePressGestureRecognizer instance) {
11891195
instance
11901196
..onStart = onForcePressStart

packages/flutter/test/widgets/gesture_detector_test.dart

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,53 @@ void main() {
875875
});
876876
});
877877
});
878+
879+
testWidgets('supportedDevices is respected', (WidgetTester tester) async {
880+
bool didStartPan = false;
881+
Offset? panDelta;
882+
bool didEndPan = false;
883+
884+
await tester.pumpWidget(
885+
GestureDetector(
886+
onPanStart: (DragStartDetails details) {
887+
didStartPan = true;
888+
},
889+
onPanUpdate: (DragUpdateDetails details) {
890+
panDelta = (panDelta ?? Offset.zero) + details.delta;
891+
},
892+
onPanEnd: (DragEndDetails details) {
893+
didEndPan = true;
894+
},
895+
supportedDevices: const <PointerDeviceKind>{PointerDeviceKind.mouse},
896+
child: Container(
897+
color: const Color(0xFF00FF00),
898+
)
899+
),
900+
);
901+
902+
expect(didStartPan, isFalse);
903+
expect(panDelta, isNull);
904+
expect(didEndPan, isFalse);
905+
906+
await tester.dragFrom(const Offset(10.0, 10.0), const Offset(20.0, 30.0), kind: PointerDeviceKind.mouse);
907+
908+
// Matching device should allow gesture.
909+
expect(didStartPan, isTrue);
910+
expect(panDelta!.dx, 20.0);
911+
expect(panDelta!.dy, 30.0);
912+
expect(didEndPan, isTrue);
913+
914+
didStartPan = false;
915+
panDelta = null;
916+
didEndPan = false;
917+
918+
await tester.dragFrom(const Offset(10.0, 10.0), const Offset(20.0, 30.0), kind: PointerDeviceKind.stylus);
919+
920+
// Non-matching device should not lead to any callbacks.
921+
expect(didStartPan, isFalse);
922+
expect(panDelta, isNull);
923+
expect(didEndPan, isFalse);
924+
});
878925
}
879926

880927
class _EmptySemanticsGestureDelegate extends SemanticsGestureDelegate {

0 commit comments

Comments
 (0)