mirror of
https://github.com/flutter/flutter
synced 2024-09-17 23:31:55 +00:00
Fix scroll offset when caret larger than viewport (#93248)
Fixing a calculation when jumping to an offset with a large caret as compared to the viewport.
This commit is contained in:
parent
2a149bc4cd
commit
1e255b137b
|
@ -2151,7 +2151,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||
if (!_isMultiline) {
|
||||
additionalOffset = rect.width >= editableSize.width
|
||||
// Center `rect` if it's oversized.
|
||||
? editableSize.width / 2 - rect.center.dx
|
||||
? rect.center.dx - editableSize.width / 2
|
||||
// Valid additional offsets range from (rect.right - size.width)
|
||||
// to (rect.left). Pick the closest one if out of range.
|
||||
: 0.0.clamp(rect.right - editableSize.width, rect.left);
|
||||
|
@ -2167,7 +2167,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||
);
|
||||
|
||||
additionalOffset = expandedRect.height >= editableSize.height
|
||||
? editableSize.height / 2 - expandedRect.center.dy
|
||||
? expandedRect.center.dy - editableSize.height / 2
|
||||
: 0.0.clamp(expandedRect.bottom - editableSize.height, expandedRect.top);
|
||||
unitOffset = const Offset(0, 1);
|
||||
}
|
||||
|
|
|
@ -5812,12 +5812,111 @@ void main() {
|
|||
state.bringIntoView(TextPosition(offset: controller.text.length));
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
// The SingleChildScrollView is scrolled instead of the EditableText to
|
||||
// reveal the caret.
|
||||
// The SingleChildScrollView is scrolled instead of the EditableText to reveal the caret.
|
||||
expect(outerController.offset, outerController.position.maxScrollExtent);
|
||||
expect(editableScrollController.offset, 0);
|
||||
});
|
||||
|
||||
testWidgets('bringIntoView centers the viewport on caret when the caret is wider than the viewport', (WidgetTester tester) async {
|
||||
const String text = 'to coz ze ze Szwecji';
|
||||
final TextEditingController controller = TextEditingController(text: text);
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: SizedBox(
|
||||
width: 32.0,
|
||||
height: 100.0,
|
||||
child: EditableText(
|
||||
showSelectionHandles: true,
|
||||
controller: controller,
|
||||
focusNode: FocusNode(),
|
||||
style: const TextStyle(fontFamily: 'Ahem', fontSize: 48.0, height: 1.0),
|
||||
cursorColor: Colors.blue,
|
||||
cursorWidth: 48.0,
|
||||
backgroundCursorColor: Colors.grey,
|
||||
selectionControls: materialTextSelectionControls,
|
||||
keyboardType: TextInputType.text,
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
final EditableTextState state = tester.state<EditableTextState>(find.byType(EditableText));
|
||||
final RenderEditable renderEditable = state.renderEditable;
|
||||
final Scrollable scrollable = tester.widget<Scrollable>(find.byType(Scrollable));
|
||||
|
||||
expect(scrollable.controller!.position.viewportDimension, equals(32.0));
|
||||
expect(scrollable.controller!.offset, 0.0);
|
||||
expect(renderEditable.maxScrollExtent, equals(977.0));
|
||||
|
||||
state.bringIntoView(const TextPosition(offset: 2));
|
||||
await tester.pumpAndSettle();
|
||||
expect(scrollable.controller!.offset, 2 * 48.0 + 48.0 / 2 - 32.0 / 2);
|
||||
|
||||
state.bringIntoView(const TextPosition(offset: 5));
|
||||
await tester.pumpAndSettle();
|
||||
expect(scrollable.controller!.offset, 5 * 48.0 + 48.0 / 2 - 32.0 / 2);
|
||||
|
||||
state.bringIntoView(const TextPosition(offset: 7));
|
||||
await tester.pumpAndSettle();
|
||||
expect(scrollable.controller!.offset, 7 * 48.0 + 48.0 / 2 - 32.0 / 2);
|
||||
|
||||
state.bringIntoView(const TextPosition(offset: 9));
|
||||
await tester.pumpAndSettle();
|
||||
expect(scrollable.controller!.offset, 9 * 48.0 + 48.0 / 2 - 32.0 / 2);
|
||||
});
|
||||
|
||||
testWidgets('bringIntoView centers the viewport on caret when the caret is taller than the viewport', (WidgetTester tester) async {
|
||||
const String text = 'to\ncoz\nze\nze\nSzwecji';
|
||||
final TextEditingController controller = TextEditingController(text: text);
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: SizedBox(
|
||||
width: 500.0,
|
||||
height: 32.0,
|
||||
child: EditableText(
|
||||
showSelectionHandles: true,
|
||||
maxLines: null,
|
||||
controller: controller,
|
||||
focusNode: FocusNode(),
|
||||
style: const TextStyle(fontFamily: 'Ahem', fontSize: 48.0, height: 1.0),
|
||||
cursorColor: Colors.blue,
|
||||
backgroundCursorColor: Colors.grey,
|
||||
selectionControls: materialTextSelectionControls,
|
||||
keyboardType: TextInputType.text,
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
final EditableTextState state = tester.state<EditableTextState>(find.byType(EditableText));
|
||||
final RenderEditable renderEditable = state.renderEditable;
|
||||
final Scrollable scrollable = tester.widget<Scrollable>(find.byType(Scrollable));
|
||||
|
||||
expect(scrollable.controller!.position.viewportDimension, equals(32.0));
|
||||
expect(scrollable.controller!.offset, 0.0);
|
||||
expect(renderEditable.maxScrollExtent, equals(208.0));
|
||||
|
||||
state.bringIntoView(const TextPosition(offset: 3));
|
||||
await tester.pumpAndSettle();
|
||||
expect(scrollable.controller!.offset, 48.0 + 48.0 / 2 - 32.0 / 2);
|
||||
|
||||
state.bringIntoView(const TextPosition(offset: 7));
|
||||
await tester.pumpAndSettle();
|
||||
expect(scrollable.controller!.offset, 2 * 48.0 + 48.0 / 2 - 32.0 / 2);
|
||||
|
||||
state.bringIntoView(const TextPosition(offset: 10));
|
||||
await tester.pumpAndSettle();
|
||||
expect(scrollable.controller!.offset, 3 * 48.0 + 48.0 / 2 - 32.0 / 2);
|
||||
|
||||
state.bringIntoView(const TextPosition(offset: 13));
|
||||
await tester.pumpAndSettle();
|
||||
expect(scrollable.controller!.offset, 4 * 48.0 + 48.0 / 2 - 32.0 / 2);
|
||||
});
|
||||
|
||||
testWidgets('bringIntoView does nothing if the physics prohibits implicit scrolling', (WidgetTester tester) async {
|
||||
final TextEditingController controller = TextEditingController(text: testText * 20);
|
||||
final ScrollController scrollController = ScrollController();
|
||||
|
@ -5844,7 +5943,6 @@ void main() {
|
|||
));
|
||||
}
|
||||
|
||||
|
||||
await buildWithPhysics();
|
||||
expect(scrollController.offset, 0);
|
||||
|
||||
|
|
Loading…
Reference in a new issue