Unverified Commit cd771404 authored by xubaolin's avatar xubaolin Committed by GitHub

TextField and last input character should visible on the screen when the...

TextField and last input character should visible on the screen when the cursor is not shown (#74722)
parent 791edc23
......@@ -383,6 +383,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
TextSelectionDelegate textSelectionDelegate;
Rect? _lastCaretRect;
late Rect _currentCaretRect;
/// Track whether position of the start of the selected text is within the viewport.
///
......@@ -2124,7 +2125,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
return Offset(pixelPerfectOffsetX, pixelPerfectOffsetY);
}
void _paintCaret(Canvas canvas, Offset effectiveOffset, TextPosition textPosition) {
void _paintCaretIfNeeded(Canvas canvas, Offset effectiveOffset, TextPosition textPosition) {
assert(_textLayoutLastMaxWidth == constraints.maxWidth &&
_textLayoutLastMinWidth == constraints.minWidth,
'Last width ($_textLayoutLastMinWidth, $_textLayoutLastMaxWidth) not the same as max width constraint (${constraints.minWidth}, ${constraints.maxWidth}).');
......@@ -2171,6 +2172,10 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
}
caretRect = caretRect.shift(_getPixelPerfectCursorOffset(caretRect));
_currentCaretRect = caretRect;
if (!_showCursor.value)
return;
if (cursorRadius == null) {
canvas.drawRect(caretRect, paint);
......@@ -2178,11 +2183,13 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
final RRect caretRRect = RRect.fromRectAndRadius(caretRect, cursorRadius!);
canvas.drawRRect(caretRRect, paint);
}
}
if (caretRect != _lastCaretRect) {
_lastCaretRect = caretRect;
void _updateCaretRect() {
if (_currentCaretRect != _lastCaretRect) {
_lastCaretRect = _currentCaretRect;
if (onCaretChanged != null)
onCaretChanged!(caretRect);
onCaretChanged!(_currentCaretRect);
}
}
......@@ -2333,11 +2340,11 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
final Offset effectiveOffset = offset + _paintOffset;
bool showSelection = false;
bool showCaret = false;
bool canShowCaret = false;
if (selection != null && !_floatingCursorOn) {
if (selection!.isCollapsed && _showCursor.value && cursorColor != null)
showCaret = true;
if (selection!.isCollapsed && cursorColor != null)
canShowCaret = true;
else if (!selection!.isCollapsed && _selectionColor != null)
showSelection = true;
_updateSelectionExtentsVisibility(effectiveOffset);
......@@ -2356,17 +2363,20 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
if (paintCursorAboveText)
_textPainter.paint(context.canvas, effectiveOffset);
if (showCaret) {
if (canShowCaret) {
assert(selection != null);
_paintCaret(context.canvas, effectiveOffset, selection!.extent);
_paintCaretIfNeeded(context.canvas, effectiveOffset, selection!.extent);
_updateCaretRect();
}
if (!paintCursorAboveText)
_textPainter.paint(context.canvas, effectiveOffset);
if (_floatingCursorOn) {
if (_resetFloatingCursorAnimationValue == null)
_paintCaret(context.canvas, effectiveOffset, _floatingCursorTextPosition);
if (_resetFloatingCursorAnimationValue == null) {
_paintCaretIfNeeded(context.canvas, effectiveOffset, _floatingCursorTextPosition);
_updateCaretRect();
}
_paintFloatingCaret(context.canvas, _floatingCursorOffset);
}
}
......
......@@ -8574,6 +8574,51 @@ void main() {
expect(scrollController.offset, 48.0);
});
// Regression test for https://github.com/flutter/flutter/issues/74566
testWidgets('TextField and last input character are visible on the screen when the cursor is not shown', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
final ScrollController textFieldScrollController = ScrollController();
await tester.pumpWidget(MaterialApp(
theme: ThemeData(),
home: Scaffold(
body: Center(
child: ListView(
controller: scrollController,
children: <Widget>[
Container(height: 579), // Push field almost off screen.
TextField(
scrollController: textFieldScrollController,
showCursor: false,
),
Container(height: 1000),
],
),
),
),
));
// Tap the TextField to bring it into view.
expect(scrollController.offset, 0.0);
await tester.tapAt(tester.getTopLeft(find.byType(TextField)));
await tester.pumpAndSettle();
// The ListView has scrolled to keep the TextField visible.
expect(scrollController.offset, 48.0);
expect(textFieldScrollController.offset, 0.0);
// After entering some long text, the last input character remains on the screen.
final String testValue = 'I love Flutter!' * 10;
tester.testTextInput.updateEditingValue(TextEditingValue(
text: testValue,
selection: TextSelection.collapsed(offset: testValue.length),
));
await tester.pump();
await tester.pumpAndSettle(); // Text scroll animation.
expect(textFieldScrollController.offset, 1602.0);
});
group('height', () {
testWidgets('By default, TextField is at least kMinInteractiveDimension high', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
......
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