diff --git a/packages/flutter/lib/src/widgets/drag_target.dart b/packages/flutter/lib/src/widgets/drag_target.dart index 34a05357b9..8f6b6973da 100644 --- a/packages/flutter/lib/src/widgets/drag_target.dart +++ b/packages/flutter/lib/src/widgets/drag_target.dart @@ -398,6 +398,7 @@ class LongPressDraggable extends Draggable { VoidCallback? onDragCompleted, this.hapticFeedbackOnStart = true, bool ignoringFeedbackSemantics = true, + this.delay = kLongPressTimeout, }) : super( key: key, child: child, @@ -419,9 +420,14 @@ class LongPressDraggable extends Draggable { /// Whether haptic feedback should be triggered on drag start. final bool hapticFeedbackOnStart; + /// The duration that a user has to press down before a long press is registered. + /// + /// Defaults to [kLongPressTimeout]. + final Duration delay; + @override DelayedMultiDragGestureRecognizer createRecognizer(GestureMultiDragStartCallback onStart) { - return DelayedMultiDragGestureRecognizer() + return DelayedMultiDragGestureRecognizer(delay: delay) ..onStart = (Offset position) { final Drag? result = onStart(position); if (result != null && hapticFeedbackOnStart) diff --git a/packages/flutter/test/widgets/draggable_test.dart b/packages/flutter/test/widgets/draggable_test.dart index eed2f7f3b7..53b4abdc2b 100644 --- a/packages/flutter/test/widgets/draggable_test.dart +++ b/packages/flutter/test/widgets/draggable_test.dart @@ -2452,6 +2452,73 @@ void main() { expect(onDragStartedCalled, isTrue); }); + testWidgets('Custom long press delay for LongPressDraggable', (WidgetTester tester) async { + bool onDragStartedCalled = false; + await tester.pumpWidget(MaterialApp( + home: LongPressDraggable( + data: 1, + delay: const Duration(seconds: 2), + child: const Text('Source'), + feedback: const Text('Dragging'), + onDragStarted: () { + onDragStartedCalled = true; + }, + ), + )); + expect(find.text('Source'), findsOneWidget); + expect(find.text('Dragging'), findsNothing); + expect(onDragStartedCalled, isFalse); + final Offset firstLocation = tester.getCenter(find.text('Source')); + await tester.startGesture(firstLocation, pointer: 7); + await tester.pump(); + expect(find.text('Source'), findsOneWidget); + expect(find.text('Dragging'), findsNothing); + expect(onDragStartedCalled, isFalse); + // Halfway into the long press duration. + await tester.pump(const Duration(seconds: 1)); + expect(find.text('Source'), findsOneWidget); + expect(find.text('Dragging'), findsNothing); + expect(onDragStartedCalled, isFalse); + // Long press draggable should be showing. + await tester.pump(const Duration(seconds: 1)); + expect(find.text('Source'), findsOneWidget); + expect(find.text('Dragging'), findsOneWidget); + expect(onDragStartedCalled, isTrue); + }); + + testWidgets('Default long press delay for LongPressDraggable', (WidgetTester tester) async { + bool onDragStartedCalled = false; + await tester.pumpWidget(MaterialApp( + home: LongPressDraggable( + data: 1, + child: const Text('Source'), + feedback: const Text('Dragging'), + onDragStarted: () { + onDragStartedCalled = true; + }, + ), + )); + expect(find.text('Source'), findsOneWidget); + expect(find.text('Dragging'), findsNothing); + expect(onDragStartedCalled, isFalse); + final Offset firstLocation = tester.getCenter(find.text('Source')); + await tester.startGesture(firstLocation, pointer: 7); + await tester.pump(); + expect(find.text('Source'), findsOneWidget); + expect(find.text('Dragging'), findsNothing); + expect(onDragStartedCalled, isFalse); + // Halfway into the long press duration. + await tester.pump(const Duration(milliseconds: 250)); + expect(find.text('Source'), findsOneWidget); + expect(find.text('Dragging'), findsNothing); + expect(onDragStartedCalled, isFalse); + // Long press draggable should be showing. + await tester.pump(const Duration(milliseconds: 250)); + expect(find.text('Source'), findsOneWidget); + expect(find.text('Dragging'), findsOneWidget); + expect(onDragStartedCalled, isTrue); + }); + testWidgets('long-press draggable calls Haptic Feedback onStart', (WidgetTester tester) async { await _testLongPressDraggableHapticFeedback(tester: tester, hapticFeedbackOnStart: true, expectedHapticFeedbackCount: 1); });