Fixed cursor blinking during selection. (#141380)

The cursor now correctly stops blinking while it's being interacted with.
This commit is contained in:
yim 2024-02-08 05:39:30 +08:00 committed by GitHub
parent 025d18d70a
commit 16e7218cd4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 58 additions and 3 deletions

View file

@ -1193,6 +1193,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
/// in detail.
EdgeInsets floatingCursorAddedMargin;
/// Returns true if the floating cursor is visible, false otherwise.
bool get floatingCursorOn => _floatingCursorOn;
bool _floatingCursorOn = false;
late TextPosition _floatingCursorTextPosition;

View file

@ -4166,7 +4166,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
_cursorVisibilityNotifier.value = widget.showCursor && (EditableText.debugDeterministicCursor || _cursorBlinkOpacityController.value > 0);
}
bool get _showBlinkingCursor => _hasFocus && _value.selection.isCollapsed && widget.showCursor && _tickersEnabled;
bool get _showBlinkingCursor => _hasFocus && _value.selection.isCollapsed && widget.showCursor && _tickersEnabled && !renderEditable.floatingCursorOn;
/// Whether the blinking cursor is actually visible at this precise moment
/// (it's hidden half the time, since it blinks).
@ -4230,7 +4230,9 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
}
void _stopCursorBlink({ bool resetCharTicks = true }) {
_cursorBlinkOpacityController.value = 0.0;
// If the cursor is animating, stop the animation, and we always
// want the cursor to be visible when the floating cursor is enabled.
_cursorBlinkOpacityController.value = renderEditable.floatingCursorOn ? 1.0 : 0.0;
_cursorTimer?.cancel();
_cursorTimer = null;
if (resetCharTicks) {

View file

@ -17838,7 +17838,6 @@ void main() {
skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu.
);
testWidgets('Start the floating cursor on long tap', (WidgetTester tester) async {
EditableText.debugDeterministicCursor = true;
final TextEditingController controller = _textEditingController(
@ -17879,6 +17878,58 @@ void main() {
},
variant: TargetPlatformVariant.only(TargetPlatform.iOS),
);
testWidgets('Cursor should not blink when long-pressing to show floating cursor.', (WidgetTester tester) async {
final TextEditingController controller = _textEditingController(
text: 'abcdefghijklmnopqr',
);
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: TextField(
autofocus: true,
controller: controller,
cursorOpacityAnimates: false
)
),
),
),
);
final EditableTextState state = tester.state(find.byType(EditableText));
Future<void> checkCursorBlinking({ bool isBlinking = true }) async {
bool initialShowCursor = true;
if (isBlinking) {
initialShowCursor = state.renderEditable.showCursor.value;
}
await tester.pump(state.cursorBlinkInterval);
expect(state.cursorCurrentlyVisible, equals(isBlinking ? !initialShowCursor : initialShowCursor));
await tester.pump(state.cursorBlinkInterval);
expect(state.cursorCurrentlyVisible, equals(initialShowCursor));
await tester.pump(state.cursorBlinkInterval);
expect(state.cursorCurrentlyVisible, equals(isBlinking ? !initialShowCursor : initialShowCursor));
await tester.pump(state.cursorBlinkInterval);
expect(state.cursorCurrentlyVisible, equals(initialShowCursor));
}
// Wait for autofocus.
await tester.pumpAndSettle();
// Before long-pressing, the cursor should blink.
await checkCursorBlinking();
final TestGesture gesture = await tester.startGesture(tester.getTopLeft(find.byType(TextField)));
await tester.pump(kLongPressTimeout);
// When long-pressing, the cursor shouldn't blink.
await checkCursorBlinking(isBlinking: false);
await gesture.moveBy(const Offset(20, 0));
await tester.pump();
// When long-pressing and dragging to move the cursor, the cursor shouldn't blink.
await checkCursorBlinking(isBlinking: false);
await gesture.up();
// After finishing the long-press, the cursor should blink.
await checkCursorBlinking();
},
variant: TargetPlatformVariant.only(TargetPlatform.iOS),
);
}
/// A Simple widget for testing the obscure text.