fix: Inconsistency of SelectionArea when scrolling (#128765)

This PR fixes inconsistency of SelectionArea when scrolling by removing the `_clearSelection` on `longPressUpdate` gesture. This in turn makes the selection UX much better.

*List which issues are fixed by this PR. You must list at least one issue.*
Fixes: https://github.com/flutter/flutter/issues/120892

*If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].*
This commit is contained in:
Paurakh Sharma Humagain 2023-06-23 22:32:47 +05:45 committed by GitHub
parent 309e50173e
commit a9164a4d76
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 2 deletions

View file

@ -439,8 +439,7 @@ class SelectableRegionState extends State<SelectableRegion> with TextSelectionDe
instance
..onLongPressStart = _handleTouchLongPressStart
..onLongPressMoveUpdate = _handleTouchLongPressMoveUpdate
..onLongPressEnd = _handleTouchLongPressEnd
..onLongPressCancel = _clearSelection;
..onLongPressEnd = _handleTouchLongPressEnd;
},
);
}

View file

@ -310,6 +310,82 @@ void main() {
expect(edgeEvent.globalPosition, const Offset(200.0, 50.0));
});
testWidgets(
'touch long press cancel does not send ClearSelectionEvent',
(WidgetTester tester) async {
final UniqueKey spy = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
selectionControls: materialTextSelectionControls,
child: SelectionSpy(key: spy),
),
),
);
await tester.pumpAndSettle();
final RenderSelectionSpy renderSelectionSpy =
tester.renderObject<RenderSelectionSpy>(find.byKey(spy));
renderSelectionSpy.events.clear();
final TestGesture gesture =
await tester.startGesture(const Offset(200.0, 200.0));
addTearDown(gesture.removePointer);
await tester.pump(const Duration(milliseconds: 500));
await gesture.cancel();
expect(
renderSelectionSpy.events.any((SelectionEvent element) => element is ClearSelectionEvent),
isFalse,
);
},
);
testWidgets(
'scrolling after the selection does not send ClearSelectionEvent',
(WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/128765
final UniqueKey spy = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: SizedBox(
height: 750,
child: SingleChildScrollView(
child: SizedBox(
height: 2000,
child: SelectableRegion(
focusNode: FocusNode(),
selectionControls: materialTextSelectionControls,
child: SelectionSpy(key: spy),
),
),
),
),
),
);
await tester.pumpAndSettle();
final RenderSelectionSpy renderSelectionSpy = tester.renderObject<RenderSelectionSpy>(find.byKey(spy));
renderSelectionSpy.events.clear();
final TestGesture selectGesture = await tester.startGesture(const Offset(200.0, 200.0));
addTearDown(selectGesture.removePointer);
await tester.pump(const Duration(milliseconds: 500));
await selectGesture.up();
expect(renderSelectionSpy.events.length, 1);
expect(renderSelectionSpy.events[0], isA<SelectWordSelectionEvent>());
renderSelectionSpy.events.clear();
final TestGesture scrollGesture =
await tester.startGesture(const Offset(250.0, 850.0));
await tester.pump(const Duration(milliseconds: 500));
await scrollGesture.moveTo(Offset.zero);
await scrollGesture.up();
await tester.pumpAndSettle();
expect(renderSelectionSpy.events.length, 0);
},
);
testWidgets('mouse long press does not send select-word event', (WidgetTester tester) async {
final UniqueKey spy = UniqueKey();
await tester.pumpWidget(