Desktop edge scrolling (#93170)
This commit is contained in:
parent
3f8e77ed17
commit
297a7c7565
@ -967,15 +967,30 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _handleSelectionChanged(TextSelection selection, SelectionChangedCause? cause) {
|
void _handleSelectionChanged(TextSelection selection, SelectionChangedCause? cause) {
|
||||||
if (cause == SelectionChangedCause.longPress) {
|
|
||||||
_editableText.bringIntoView(selection.base);
|
|
||||||
}
|
|
||||||
final bool willShowSelectionHandles = _shouldShowSelectionHandles(cause);
|
final bool willShowSelectionHandles = _shouldShowSelectionHandles(cause);
|
||||||
if (willShowSelectionHandles != _showSelectionHandles) {
|
if (willShowSelectionHandles != _showSelectionHandles) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_showSelectionHandles = willShowSelectionHandles;
|
_showSelectionHandles = willShowSelectionHandles;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (defaultTargetPlatform) {
|
||||||
|
case TargetPlatform.iOS:
|
||||||
|
case TargetPlatform.macOS:
|
||||||
|
if (cause == SelectionChangedCause.longPress
|
||||||
|
|| cause == SelectionChangedCause.drag) {
|
||||||
|
_editableText.bringIntoView(selection.extent);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case TargetPlatform.linux:
|
||||||
|
case TargetPlatform.windows:
|
||||||
|
case TargetPlatform.fuchsia:
|
||||||
|
case TargetPlatform.android:
|
||||||
|
if (cause == SelectionChangedCause.drag) {
|
||||||
|
_editableText.bringIntoView(selection.extent);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -614,7 +614,13 @@ class HorizontalDragGestureRecognizer extends DragGestureRecognizer {
|
|||||||
/// some time has passed.
|
/// some time has passed.
|
||||||
class PanGestureRecognizer extends DragGestureRecognizer {
|
class PanGestureRecognizer extends DragGestureRecognizer {
|
||||||
/// Create a gesture recognizer for tracking movement on a plane.
|
/// Create a gesture recognizer for tracking movement on a plane.
|
||||||
PanGestureRecognizer({ Object? debugOwner }) : super(debugOwner: debugOwner);
|
PanGestureRecognizer({
|
||||||
|
Object? debugOwner,
|
||||||
|
Set<PointerDeviceKind>? supportedDevices,
|
||||||
|
}) : super(
|
||||||
|
debugOwner: debugOwner,
|
||||||
|
supportedDevices: supportedDevices,
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool isFlingGesture(VelocityEstimate estimate, PointerDeviceKind kind) {
|
bool isFlingGesture(VelocityEstimate estimate, PointerDeviceKind kind) {
|
||||||
|
@ -1075,15 +1075,19 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
|
|||||||
switch (Theme.of(context).platform) {
|
switch (Theme.of(context).platform) {
|
||||||
case TargetPlatform.iOS:
|
case TargetPlatform.iOS:
|
||||||
case TargetPlatform.macOS:
|
case TargetPlatform.macOS:
|
||||||
if (cause == SelectionChangedCause.longPress) {
|
if (cause == SelectionChangedCause.longPress
|
||||||
_editableText?.bringIntoView(selection.base);
|
|| cause == SelectionChangedCause.drag) {
|
||||||
|
_editableText?.bringIntoView(selection.extent);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case TargetPlatform.android:
|
|
||||||
case TargetPlatform.fuchsia:
|
|
||||||
case TargetPlatform.linux:
|
case TargetPlatform.linux:
|
||||||
case TargetPlatform.windows:
|
case TargetPlatform.windows:
|
||||||
// Do nothing.
|
case TargetPlatform.fuchsia:
|
||||||
|
case TargetPlatform.android:
|
||||||
|
if (cause == SelectionChangedCause.drag) {
|
||||||
|
_editableText?.bringIntoView(selection.extent);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1527,11 +1527,9 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec
|
|||||||
if (widget.onDragSelectionStart != null ||
|
if (widget.onDragSelectionStart != null ||
|
||||||
widget.onDragSelectionUpdate != null ||
|
widget.onDragSelectionUpdate != null ||
|
||||||
widget.onDragSelectionEnd != null) {
|
widget.onDragSelectionEnd != null) {
|
||||||
// TODO(mdebbar): Support dragging in any direction (for multiline text).
|
gestures[PanGestureRecognizer] = GestureRecognizerFactoryWithHandlers<PanGestureRecognizer>(
|
||||||
// https://github.com/flutter/flutter/issues/28676
|
() => PanGestureRecognizer(debugOwner: this, supportedDevices: <PointerDeviceKind>{ PointerDeviceKind.mouse }),
|
||||||
gestures[HorizontalDragGestureRecognizer] = GestureRecognizerFactoryWithHandlers<HorizontalDragGestureRecognizer>(
|
(PanGestureRecognizer instance) {
|
||||||
() => HorizontalDragGestureRecognizer(debugOwner: this, kind: PointerDeviceKind.mouse),
|
|
||||||
(HorizontalDragGestureRecognizer instance) {
|
|
||||||
instance
|
instance
|
||||||
// Text selection should start from the position of the first pointer
|
// Text selection should start from the position of the first pointer
|
||||||
// down event.
|
// down event.
|
||||||
|
@ -2414,7 +2414,7 @@ void main() {
|
|||||||
expect(firstCharEndpoint.length, 1);
|
expect(firstCharEndpoint.length, 1);
|
||||||
// The first character is now offscreen to the left.
|
// The first character is now offscreen to the left.
|
||||||
expect(firstCharEndpoint[0].point.dx, moreOrLessEquals(-308.20, epsilon: 0.25));
|
expect(firstCharEndpoint[0].point.dx, moreOrLessEquals(-308.20, epsilon: 0.25));
|
||||||
});
|
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'long tap after a double tap select is not affected',
|
'long tap after a double tap select is not affected',
|
||||||
|
@ -7794,9 +7794,379 @@ void main() {
|
|||||||
);
|
);
|
||||||
expect(firstCharEndpoint.length, 1);
|
expect(firstCharEndpoint.length, 1);
|
||||||
// The first character is now offscreen to the left.
|
// The first character is now offscreen to the left.
|
||||||
expect(firstCharEndpoint[0].point.dx, moreOrLessEquals(-257, epsilon: 1));
|
expect(firstCharEndpoint[0].point.dx, moreOrLessEquals(-257.0, epsilon: 1));
|
||||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||||
|
|
||||||
|
testWidgets('mouse click and drag can edge scroll', (WidgetTester tester) async {
|
||||||
|
final TextEditingController controller = TextEditingController(
|
||||||
|
text: 'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges',
|
||||||
|
);
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: Center(
|
||||||
|
child: TextField(
|
||||||
|
controller: controller,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Just testing the test and making sure that the last character is off
|
||||||
|
// the right side of the screen.
|
||||||
|
expect(textOffsetToPosition(tester, 66).dx, 1056);
|
||||||
|
|
||||||
|
final TestGesture gesture =
|
||||||
|
await tester.startGesture(
|
||||||
|
textOffsetToPosition(tester, 19),
|
||||||
|
pointer: 7,
|
||||||
|
kind: PointerDeviceKind.mouse,
|
||||||
|
);
|
||||||
|
addTearDown(gesture.removePointer);
|
||||||
|
|
||||||
|
await gesture.moveTo(textOffsetToPosition(tester, 56));
|
||||||
|
// To the edge of the screen basically.
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection(baseOffset: 19, extentOffset: 56),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Keep moving out.
|
||||||
|
await gesture.moveTo(textOffsetToPosition(tester, 62));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection(baseOffset: 19, extentOffset: 62),
|
||||||
|
);
|
||||||
|
await gesture.moveTo(textOffsetToPosition(tester, 66));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection(baseOffset: 19, extentOffset: 66),
|
||||||
|
); // We're at the edge now.
|
||||||
|
expect(find.byType(CupertinoButton), findsNothing);
|
||||||
|
|
||||||
|
await gesture.up();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// The selection isn't affected by the gesture lift.
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection(baseOffset: 19, extentOffset: 66),
|
||||||
|
);
|
||||||
|
|
||||||
|
// The last character is now on screen near the right edge.
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, 66).dx,
|
||||||
|
moreOrLessEquals(TestSemantics.fullScreen.width, epsilon: 2.0),
|
||||||
|
);
|
||||||
|
|
||||||
|
// The first character is now offscreen to the left.
|
||||||
|
expect(textOffsetToPosition(tester, 0).dx, moreOrLessEquals(-257.0, epsilon: 1));
|
||||||
|
}, variant: TargetPlatformVariant.all());
|
||||||
|
|
||||||
|
testWidgets('keyboard selection change scrolls the field', (WidgetTester tester) async {
|
||||||
|
final TextEditingController controller = TextEditingController(
|
||||||
|
text: 'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges',
|
||||||
|
);
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: Center(
|
||||||
|
child: TextField(
|
||||||
|
controller: controller,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Just testing the test and making sure that the last character is off
|
||||||
|
// the right side of the screen.
|
||||||
|
expect(textOffsetToPosition(tester, 66).dx, 1056);
|
||||||
|
|
||||||
|
await tester.tapAt(textOffsetToPosition(tester, 13));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection.collapsed(offset: 13),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Move to position 56 with the right arrow (near the edge of the screen).
|
||||||
|
for (int i = 0; i < (56 - 13); i += 1) {
|
||||||
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
|
||||||
|
}
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection.collapsed(offset: 56),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Keep moving out.
|
||||||
|
for (int i = 0; i < (62 - 56); i += 1) {
|
||||||
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
|
||||||
|
}
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection.collapsed(offset: 62),
|
||||||
|
);
|
||||||
|
for (int i = 0; i < (66 - 62); i += 1) {
|
||||||
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
|
||||||
|
}
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection.collapsed(offset: 66),
|
||||||
|
); // We're at the edge now.
|
||||||
|
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// The last character is now on screen near the right edge.
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, 66).dx,
|
||||||
|
moreOrLessEquals(TestSemantics.fullScreen.width, epsilon: 2.0),
|
||||||
|
);
|
||||||
|
|
||||||
|
// The first character is now offscreen to the left.
|
||||||
|
expect(textOffsetToPosition(tester, 0).dx, moreOrLessEquals(-257.0, epsilon: 1));
|
||||||
|
}, variant: TargetPlatformVariant.all(),
|
||||||
|
skip: isBrowser, // [intended] Browser handles arrow keys differently.
|
||||||
|
);
|
||||||
|
|
||||||
|
testWidgets('long press drag can edge scroll vertically', (WidgetTester tester) async {
|
||||||
|
final TextEditingController controller = TextEditingController(
|
||||||
|
text: 'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neigse Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges',
|
||||||
|
);
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: Center(
|
||||||
|
child: TextField(
|
||||||
|
maxLines: 2,
|
||||||
|
controller: controller,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Just testing the test and making sure that the last character is outside
|
||||||
|
// the bottom of the field.
|
||||||
|
final int textLength = controller.text.length;
|
||||||
|
final double lineHeight = findRenderEditable(tester).preferredLineHeight;
|
||||||
|
final double firstCharY = textOffsetToPosition(tester, 0).dy;
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, textLength).dy,
|
||||||
|
moreOrLessEquals(firstCharY + lineHeight * 2, epsilon: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Start long pressing on the first line.
|
||||||
|
final TestGesture gesture =
|
||||||
|
await tester.startGesture(textOffsetToPosition(tester, 19));
|
||||||
|
// TODO(justinmc): Make sure you've got all things torn down.
|
||||||
|
addTearDown(gesture.removePointer);
|
||||||
|
await tester.pump(const Duration(milliseconds: 500));
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection.collapsed(offset: 19),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// Move down to the second line.
|
||||||
|
await gesture.moveBy(Offset(0.0, lineHeight));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection.collapsed(offset: 65),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Still hasn't scrolled.
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, 65).dy,
|
||||||
|
moreOrLessEquals(firstCharY + lineHeight, epsilon: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Keep selecting down to the third and final line.
|
||||||
|
await gesture.moveBy(Offset(0.0, lineHeight));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection.collapsed(offset: 110),
|
||||||
|
);
|
||||||
|
|
||||||
|
// The last character is no longer three line heights down from the top of
|
||||||
|
// the field, it's now only two line heights down, because it has scrolled
|
||||||
|
// down by one line.
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, 110).dy,
|
||||||
|
moreOrLessEquals(firstCharY + lineHeight, epsilon: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Likewise, the first character is now scrolled out of the top of the field
|
||||||
|
// by one line.
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, 0).dy,
|
||||||
|
moreOrLessEquals(firstCharY - lineHeight, epsilon: 1),
|
||||||
|
);
|
||||||
|
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||||
|
|
||||||
|
testWidgets('keyboard selection change scrolls the field vertically', (WidgetTester tester) async {
|
||||||
|
final TextEditingController controller = TextEditingController(
|
||||||
|
text: 'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges',
|
||||||
|
);
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: Center(
|
||||||
|
child: TextField(
|
||||||
|
maxLines: 2,
|
||||||
|
controller: controller,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Just testing the test and making sure that the last character is outside
|
||||||
|
// the bottom of the field.
|
||||||
|
final int textLength = controller.text.length;
|
||||||
|
final double lineHeight = findRenderEditable(tester).preferredLineHeight;
|
||||||
|
final double firstCharY = textOffsetToPosition(tester, 0).dy;
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, textLength).dy,
|
||||||
|
moreOrLessEquals(firstCharY + lineHeight * 2, epsilon: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.tapAt(textOffsetToPosition(tester, 13));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection.collapsed(offset: 13),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Move down to the second line.
|
||||||
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection.collapsed(offset: 59),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Still hasn't scrolled.
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, 66).dy,
|
||||||
|
moreOrLessEquals(firstCharY + lineHeight, epsilon: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Move down to the third and final line.
|
||||||
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection.collapsed(offset: 104),
|
||||||
|
);
|
||||||
|
|
||||||
|
// The last character is no longer three line heights down from the top of
|
||||||
|
// the field, it's now only two line heights down, because it has scrolled
|
||||||
|
// down by one line.
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, textLength).dy,
|
||||||
|
moreOrLessEquals(firstCharY + lineHeight, epsilon: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Likewise, the first character is now scrolled out of the top of the field
|
||||||
|
// by one line.
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, 0).dy,
|
||||||
|
moreOrLessEquals(firstCharY - lineHeight, epsilon: 1),
|
||||||
|
);
|
||||||
|
}, variant: TargetPlatformVariant.all(),
|
||||||
|
skip: isBrowser, // [intended] Browser handles arrow keys differently.
|
||||||
|
);
|
||||||
|
|
||||||
|
testWidgets('mouse click and drag can edge scroll vertically', (WidgetTester tester) async {
|
||||||
|
final TextEditingController controller = TextEditingController(
|
||||||
|
text: 'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges',
|
||||||
|
);
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: Center(
|
||||||
|
child: TextField(
|
||||||
|
maxLines: 2,
|
||||||
|
controller: controller,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Just testing the test and making sure that the last character is outside
|
||||||
|
// the bottom of the field.
|
||||||
|
final int textLength = controller.text.length;
|
||||||
|
final double lineHeight = findRenderEditable(tester).preferredLineHeight;
|
||||||
|
final double firstCharY = textOffsetToPosition(tester, 0).dy;
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, textLength).dy,
|
||||||
|
moreOrLessEquals(firstCharY + lineHeight * 2, epsilon: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Start selecting on the first line.
|
||||||
|
final TestGesture gesture =
|
||||||
|
await tester.startGesture(
|
||||||
|
textOffsetToPosition(tester, 19),
|
||||||
|
pointer: 7,
|
||||||
|
kind: PointerDeviceKind.mouse,
|
||||||
|
);
|
||||||
|
addTearDown(gesture.removePointer);
|
||||||
|
|
||||||
|
// Still hasn't scrolled.
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, 60).dy,
|
||||||
|
moreOrLessEquals(firstCharY + lineHeight, epsilon: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Select down to the second line.
|
||||||
|
await gesture.moveBy(Offset(0.0, lineHeight));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection(baseOffset: 19, extentOffset: 65),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Still hasn't scrolled.
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, 60).dy,
|
||||||
|
moreOrLessEquals(firstCharY + lineHeight, epsilon: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Keep selecting down to the third and final line.
|
||||||
|
await gesture.moveBy(Offset(0.0, lineHeight));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
controller.selection,
|
||||||
|
const TextSelection(baseOffset: 19, extentOffset: 110),
|
||||||
|
);
|
||||||
|
|
||||||
|
// The last character is no longer three line heights down from the top of
|
||||||
|
// the field, it's now only two line heights down, because it has scrolled
|
||||||
|
// down by one line.
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, textLength).dy,
|
||||||
|
moreOrLessEquals(firstCharY + lineHeight, epsilon: 1),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Likewise, the first character is now scrolled out of the top of the field
|
||||||
|
// by one line.
|
||||||
|
expect(
|
||||||
|
textOffsetToPosition(tester, 0).dy,
|
||||||
|
moreOrLessEquals(firstCharY - lineHeight, epsilon: 1),
|
||||||
|
);
|
||||||
|
}, variant: TargetPlatformVariant.all());
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'long tap after a double tap select is not affected',
|
'long tap after a double tap select is not affected',
|
||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user