Commit 924c206c authored by Alex Allen's avatar Alex Allen Committed by xster

Add optional haptic feedback on LongPressDraggable (#18781)

parent a66ea0a6
......@@ -267,6 +267,7 @@ class LongPressDraggable<T> extends Draggable<T> {
VoidCallback onDragStarted,
DraggableCanceledCallback onDraggableCanceled,
VoidCallback onDragCompleted,
this.hapticFeedbackOnStart = true,
bool ignoringFeedbackSemantics = true,
}) : super(
key: key,
......@@ -284,12 +285,15 @@ class LongPressDraggable<T> extends Draggable<T> {
ignoringFeedbackSemantics: ignoringFeedbackSemantics,
);
/// Whether haptic feedback should be triggered on drag start.
final bool hapticFeedbackOnStart;
@override
DelayedMultiDragGestureRecognizer createRecognizer(GestureMultiDragStartCallback onStart) {
return new DelayedMultiDragGestureRecognizer()
..onStart = (Offset position) {
final Drag result = onStart(position);
if (result != null)
if (result != null && hapticFeedbackOnStart)
HapticFeedback.vibrate();
return result;
};
......
......@@ -4,6 +4,7 @@
import 'package:flutter/semantics.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
......@@ -1635,6 +1636,14 @@ void main() {
expect(onDragStartedCalled, isTrue);
});
testWidgets('long-press draggable calls Haptic Feedback onStart', (WidgetTester tester) async {
await _testLongPressDraggableHapticFeedback(tester: tester, hapticFeedbackOnStart: true, expectedHapticFeedbackCount: 1);
});
testWidgets('long-press draggable can disable Haptic Feedback', (WidgetTester tester) async {
await _testLongPressDraggableHapticFeedback(tester: tester, hapticFeedbackOnStart: false, expectedHapticFeedbackCount: 0);
});
testWidgets('Drag feedback with child anchor positions correctly', (WidgetTester tester) async {
await _testChildAnchorFeedbackPosition(tester: tester);
});
......@@ -1793,6 +1802,48 @@ void main() {
}
Future<Null> _testLongPressDraggableHapticFeedback({WidgetTester tester, bool hapticFeedbackOnStart, int expectedHapticFeedbackCount}) async {
bool onDragStartedCalled = false;
int hapticFeedbackCalls = 0;
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
if (methodCall.method == 'HapticFeedback.vibrate') {
hapticFeedbackCalls++;
}
});
await tester.pumpWidget(new MaterialApp(
home: new LongPressDraggable<int>(
data: 1,
child: const Text('Source'),
feedback: const Text('Dragging'),
hapticFeedbackOnStart: hapticFeedbackOnStart,
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);
await tester.pump(kLongPressTimeout);
expect(find.text('Source'), findsOneWidget);
expect(find.text('Dragging'), findsOneWidget);
expect(onDragStartedCalled, isTrue);
expect(hapticFeedbackCalls, expectedHapticFeedbackCount);
}
Future<Null> _testChildAnchorFeedbackPosition({WidgetTester tester, double top = 0.0, double left = 0.0}) async {
final List<int> accepted = <int>[];
int dragStartedCount = 0;
......
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