Fix selection menu not showing after clear (#37042)
This allows the text selection menu to be shown after deleting all text in a text field.
This commit is contained in:
parent
53a1f225ae
commit
d82bca2a31
@ -1061,7 +1061,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value.text != _value.text) {
|
if (value.text != _value.text) {
|
||||||
_hideSelectionOverlayIfNeeded();
|
hideToolbar();
|
||||||
_showCaretOnScreen();
|
_showCaretOnScreen();
|
||||||
if (widget.obscureText && value.text.length == _value.text.length + 1) {
|
if (widget.obscureText && value.text.length == _value.text.length + 1) {
|
||||||
_obscureShowCharTicksPending = _kObscureShowLatestCharCursorTicks;
|
_obscureShowCharTicksPending = _kObscureShowLatestCharCursorTicks;
|
||||||
@ -1300,11 +1300,6 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _hideSelectionOverlayIfNeeded() {
|
|
||||||
_selectionOverlay?.hide();
|
|
||||||
_selectionOverlay = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _updateOrDisposeSelectionOverlayIfNeeded() {
|
void _updateOrDisposeSelectionOverlayIfNeeded() {
|
||||||
if (_selectionOverlay != null) {
|
if (_selectionOverlay != null) {
|
||||||
if (_hasFocus) {
|
if (_hasFocus) {
|
||||||
@ -1323,7 +1318,8 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
// EditableWidget, not just changes triggered by user gestures.
|
// EditableWidget, not just changes triggered by user gestures.
|
||||||
requestKeyboard();
|
requestKeyboard();
|
||||||
|
|
||||||
_hideSelectionOverlayIfNeeded();
|
_selectionOverlay?.hide();
|
||||||
|
_selectionOverlay = null;
|
||||||
|
|
||||||
if (widget.selectionControls != null) {
|
if (widget.selectionControls != null) {
|
||||||
_selectionOverlay = TextSelectionOverlay(
|
_selectionOverlay = TextSelectionOverlay(
|
||||||
|
@ -16,7 +16,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'editable_text_utils.dart';
|
import 'editable_text_utils.dart';
|
||||||
import 'semantics_tester.dart';
|
import 'semantics_tester.dart';
|
||||||
|
|
||||||
final TextEditingController controller = TextEditingController();
|
TextEditingController controller;
|
||||||
final FocusNode focusNode = FocusNode(debugLabel: 'EditableText Node');
|
final FocusNode focusNode = FocusNode(debugLabel: 'EditableText Node');
|
||||||
final FocusScopeNode focusScopeNode = FocusScopeNode(debugLabel: 'EditableText Scope Node');
|
final FocusScopeNode focusScopeNode = FocusScopeNode(debugLabel: 'EditableText Scope Node');
|
||||||
const TextStyle textStyle = TextStyle();
|
const TextStyle textStyle = TextStyle();
|
||||||
@ -29,6 +29,12 @@ enum HandlePositionInViewport {
|
|||||||
void main() {
|
void main() {
|
||||||
setUp(() {
|
setUp(() {
|
||||||
debugResetSemanticsIdCounter();
|
debugResetSemanticsIdCounter();
|
||||||
|
controller = TextEditingController();
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDown(() {
|
||||||
|
controller.dispose();
|
||||||
|
controller = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Tests that the desired keyboard action button is requested.
|
// Tests that the desired keyboard action button is requested.
|
||||||
@ -528,7 +534,7 @@ void main() {
|
|||||||
equals('TextInputAction.done'));
|
equals('TextInputAction.done'));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('can only show toolbar when there is text and a selection', (WidgetTester tester) async {
|
testWidgets('can show toolbar when there is text and a selection', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
home: EditableText(
|
home: EditableText(
|
||||||
@ -545,17 +551,12 @@ void main() {
|
|||||||
final EditableTextState state =
|
final EditableTextState state =
|
||||||
tester.state<EditableTextState>(find.byType(EditableText));
|
tester.state<EditableTextState>(find.byType(EditableText));
|
||||||
|
|
||||||
|
// Can't show the toolbar when there's no focus.
|
||||||
expect(state.showToolbar(), false);
|
expect(state.showToolbar(), false);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(find.text('PASTE'), findsNothing);
|
expect(find.text('PASTE'), findsNothing);
|
||||||
|
|
||||||
controller.text = 'blah';
|
// Can show the toolbar when focused even though there's no text.
|
||||||
await tester.pump();
|
|
||||||
expect(state.showToolbar(), false);
|
|
||||||
await tester.pump();
|
|
||||||
expect(find.text('PASTE'), findsNothing);
|
|
||||||
|
|
||||||
// Select something. Doesn't really matter what.
|
|
||||||
state.renderEditable.selectWordsInRange(
|
state.renderEditable.selectWordsInRange(
|
||||||
from: const Offset(0, 0),
|
from: const Offset(0, 0),
|
||||||
cause: SelectionChangedCause.tap,
|
cause: SelectionChangedCause.tap,
|
||||||
@ -564,6 +565,58 @@ void main() {
|
|||||||
expect(state.showToolbar(), true);
|
expect(state.showToolbar(), true);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(find.text('PASTE'), findsOneWidget);
|
expect(find.text('PASTE'), findsOneWidget);
|
||||||
|
|
||||||
|
// Hide the menu again.
|
||||||
|
state.hideToolbar();
|
||||||
|
await tester.pump();
|
||||||
|
expect(find.text('PASTE'), findsNothing);
|
||||||
|
|
||||||
|
// Can show the menu with text and a selection.
|
||||||
|
controller.text = 'blah';
|
||||||
|
await tester.pump();
|
||||||
|
expect(state.showToolbar(), true);
|
||||||
|
await tester.pump();
|
||||||
|
expect(find.text('PASTE'), findsOneWidget);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('can show the toolbar after clearing all text', (WidgetTester tester) async {
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/35998.
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: EditableText(
|
||||||
|
backgroundCursorColor: Colors.grey,
|
||||||
|
controller: controller,
|
||||||
|
focusNode: focusNode,
|
||||||
|
style: textStyle,
|
||||||
|
cursorColor: cursorColor,
|
||||||
|
selectionControls: materialTextSelectionControls,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final EditableTextState state =
|
||||||
|
tester.state<EditableTextState>(find.byType(EditableText));
|
||||||
|
|
||||||
|
// Add text and an empty selection.
|
||||||
|
controller.text = 'blah';
|
||||||
|
await tester.pump();
|
||||||
|
state.renderEditable.selectWordsInRange(
|
||||||
|
from: const Offset(0, 0),
|
||||||
|
cause: SelectionChangedCause.tap,
|
||||||
|
);
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
// Clear the text and selection.
|
||||||
|
expect(find.text('PASTE'), findsNothing);
|
||||||
|
state.updateEditingValue(const TextEditingValue(
|
||||||
|
text: '',
|
||||||
|
));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
// Should be able to show the toolbar.
|
||||||
|
expect(state.showToolbar(), true);
|
||||||
|
await tester.pump();
|
||||||
|
expect(find.text('PASTE'), findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Fires onChanged when text changes via TextSelectionOverlay', (WidgetTester tester) async {
|
testWidgets('Fires onChanged when text changes via TextSelectionOverlay', (WidgetTester tester) async {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user