Skip to content

Commit 4ff7fc6

Browse files
authored
Fixes a bug where dragging a collapsed handle in TextField does not vibrate (#115586)
1 parent a5a368c commit 4ff7fc6

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,8 +1163,7 @@ class SelectionOverlay {
11631163
set selectionEndpoints(List<TextSelectionPoint> value) {
11641164
if (!listEquals(_selectionEndpoints, value)) {
11651165
markNeedsBuild();
1166-
if ((_isDraggingEndHandle || _isDraggingStartHandle) &&
1167-
_startHandleType != TextSelectionHandleType.collapsed) {
1166+
if (_isDraggingEndHandle || _isDraggingStartHandle) {
11681167
switch(defaultTargetPlatform) {
11691168
case TargetPlatform.android:
11701169
HapticFeedback.selectionClick();

packages/flutter/test/material/text_field_test.dart

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2532,6 +2532,61 @@ void main() {
25322532
expect(feedback.hapticCount, 2);
25332533
});
25342534

2535+
testWidgets('Draging a collapsed handle should trigger feedback.', (WidgetTester tester) async {
2536+
final FeedbackTester feedback = FeedbackTester();
2537+
addTearDown(feedback.dispose);
2538+
final TextEditingController controller = TextEditingController();
2539+
await tester.pumpWidget(
2540+
overlay(
2541+
child: TextField(
2542+
dragStartBehavior: DragStartBehavior.down,
2543+
controller: controller,
2544+
),
2545+
),
2546+
);
2547+
2548+
const String testValue = 'abc def ghi';
2549+
await tester.enterText(find.byType(TextField), testValue);
2550+
expect(feedback.hapticCount, 0);
2551+
await skipPastScrollingAnimation(tester);
2552+
2553+
// Tap the 'e' to bring up a collapsed handle.
2554+
final Offset ePos = textOffsetToPosition(tester, testValue.indexOf('e'));
2555+
TestGesture gesture = await tester.startGesture(ePos, pointer: 7);
2556+
await tester.pump();
2557+
await gesture.up();
2558+
await tester.pump();
2559+
await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is zero
2560+
2561+
final TextSelection selection = controller.selection;
2562+
expect(selection.baseOffset, 5);
2563+
expect(selection.extentOffset, 5);
2564+
expect(feedback.hapticCount, 0);
2565+
2566+
final RenderEditable renderEditable = findRenderEditable(tester);
2567+
final List<TextSelectionPoint> endpoints = globalize(
2568+
renderEditable.getEndpointsForSelection(selection),
2569+
renderEditable,
2570+
);
2571+
expect(endpoints.length, 1);
2572+
2573+
// Drag the right handle 3 letters to the right.
2574+
// Use a small offset because the endpoint is on the very corner
2575+
// of the handle.
2576+
final Offset handlePos = endpoints[0].point + const Offset(1.0, 1.0);
2577+
final Offset newHandlePos = textOffsetToPosition(tester, testValue.indexOf('g'));
2578+
gesture = await tester.startGesture(handlePos, pointer: 7);
2579+
await tester.pump();
2580+
await gesture.moveTo(newHandlePos);
2581+
await tester.pump();
2582+
await gesture.up();
2583+
await tester.pump();
2584+
2585+
expect(controller.selection.baseOffset, 8);
2586+
expect(controller.selection.extentOffset, 8);
2587+
expect(feedback.hapticCount, 1);
2588+
});
2589+
25352590
testWidgets('Cannot drag one handle past the other', (WidgetTester tester) async {
25362591
final TextEditingController controller = TextEditingController();
25372592

0 commit comments

Comments
 (0)