Finalize editing when hitting the enter key on a single line TextField (#23015)
Behavior remains the same for multiline TextFields. This behavior already happens on iOS and Android, but not desktop. #23014
This commit is contained in:
parent
ffa8a1ebe8
commit
d556d2117d
@ -511,44 +511,43 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
||||
void performAction(TextInputAction action) {
|
||||
switch (action) {
|
||||
case TextInputAction.newline:
|
||||
// Do nothing for a "newline" action: the newline is already inserted.
|
||||
// If this is a multiline EditableText, do nothing for a "newline"
|
||||
// action; The newline is already inserted. Otherwise, finalize
|
||||
// editing.
|
||||
if (widget.maxLines == 1)
|
||||
_finalizeEditing(true);
|
||||
break;
|
||||
case TextInputAction.done:
|
||||
case TextInputAction.go:
|
||||
case TextInputAction.send:
|
||||
case TextInputAction.search:
|
||||
// Take any actions necessary now that the user has completed editing.
|
||||
if (widget.onEditingComplete != null) {
|
||||
widget.onEditingComplete();
|
||||
} else {
|
||||
// Default behavior if the developer did not provide an
|
||||
// onEditingComplete callback: Finalize editing and remove focus.
|
||||
widget.controller.clearComposing();
|
||||
widget.focusNode.unfocus();
|
||||
}
|
||||
|
||||
// Invoke optional callback with the user's submitted content.
|
||||
if (widget.onSubmitted != null)
|
||||
widget.onSubmitted(_value.text);
|
||||
_finalizeEditing(true);
|
||||
break;
|
||||
default:
|
||||
if (widget.onEditingComplete != null) {
|
||||
widget.onEditingComplete();
|
||||
} else {
|
||||
// Default behavior if the developer did not provide an
|
||||
// onEditingComplete callback: Finalize editing, but don't give up
|
||||
// focus because this keyboard action does not imply the user is done
|
||||
// inputting information.
|
||||
widget.controller.clearComposing();
|
||||
}
|
||||
|
||||
// Invoke optional callback with the user's submitted content.
|
||||
if (widget.onSubmitted != null)
|
||||
widget.onSubmitted(_value.text);
|
||||
// Finalize editing, but don't give up focus because this keyboard
|
||||
// action does not imply the user is done inputting information.
|
||||
_finalizeEditing(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _finalizeEditing(bool shouldUnfocus) {
|
||||
// Take any actions necessary now that the user has completed editing.
|
||||
if (widget.onEditingComplete != null) {
|
||||
widget.onEditingComplete();
|
||||
} else {
|
||||
// Default behavior if the developer did not provide an
|
||||
// onEditingComplete callback: Finalize editing and remove focus.
|
||||
widget.controller.clearComposing();
|
||||
if (shouldUnfocus)
|
||||
widget.focusNode.unfocus();
|
||||
}
|
||||
|
||||
// Invoke optional callback with the user's submitted content.
|
||||
if (widget.onSubmitted != null)
|
||||
widget.onSubmitted(_value.text);
|
||||
}
|
||||
|
||||
void _updateRemoteEditingValueIfNeeded() {
|
||||
if (!_hasInputConnection)
|
||||
return;
|
||||
|
@ -745,6 +745,94 @@ void main() {
|
||||
// and onSubmission callbacks.
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'When "newline" action is called on a Editable text with maxLines == 1 callbacks are invoked: onEditingComplete > onSubmitted',
|
||||
(WidgetTester tester) async {
|
||||
final GlobalKey<EditableTextState> editableTextKey =
|
||||
GlobalKey<EditableTextState>();
|
||||
final FocusNode focusNode = FocusNode();
|
||||
|
||||
bool onEditingCompleteCalled = false;
|
||||
bool onSubmittedCalled = false;
|
||||
|
||||
final Widget widget = MaterialApp(
|
||||
home: EditableText(
|
||||
key: editableTextKey,
|
||||
controller: TextEditingController(),
|
||||
focusNode: focusNode,
|
||||
style: Typography(platform: TargetPlatform.android).black.subhead,
|
||||
cursorColor: Colors.blue,
|
||||
maxLines: 1,
|
||||
onEditingComplete: () {
|
||||
onEditingCompleteCalled = true;
|
||||
assert(!onSubmittedCalled);
|
||||
},
|
||||
onSubmitted: (String value) {
|
||||
onSubmittedCalled = true;
|
||||
assert(onEditingCompleteCalled);
|
||||
},
|
||||
),
|
||||
);
|
||||
await tester.pumpWidget(widget);
|
||||
|
||||
// Select EditableText to give it focus.
|
||||
final Finder textFinder = find.byKey(editableTextKey);
|
||||
await tester.tap(textFinder);
|
||||
await tester.pump();
|
||||
|
||||
assert(focusNode.hasFocus);
|
||||
|
||||
// The execution path starting with receiveAction() will trigger the
|
||||
// onEditingComplete and onSubmission callbacks.
|
||||
await tester.testTextInput.receiveAction(TextInputAction.newline);
|
||||
// The expectations we care about are up above in the onEditingComplete
|
||||
// and onSubmission callbacks.
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'When "newline" action is called on a Editable text with maxLines != 1, onEditingComplete and onSubmitted callbacks are not invoked.',
|
||||
(WidgetTester tester) async {
|
||||
final GlobalKey<EditableTextState> editableTextKey =
|
||||
GlobalKey<EditableTextState>();
|
||||
final FocusNode focusNode = FocusNode();
|
||||
|
||||
bool onEditingCompleteCalled = false;
|
||||
bool onSubmittedCalled = false;
|
||||
|
||||
final Widget widget = MaterialApp(
|
||||
home: EditableText(
|
||||
key: editableTextKey,
|
||||
controller: TextEditingController(),
|
||||
focusNode: focusNode,
|
||||
style: Typography(platform: TargetPlatform.android).black.subhead,
|
||||
cursorColor: Colors.blue,
|
||||
maxLines: 3,
|
||||
onEditingComplete: () {
|
||||
onEditingCompleteCalled = true;
|
||||
},
|
||||
onSubmitted: (String value) {
|
||||
onSubmittedCalled = true;
|
||||
},
|
||||
),
|
||||
);
|
||||
await tester.pumpWidget(widget);
|
||||
|
||||
// Select EditableText to give it focus.
|
||||
final Finder textFinder = find.byKey(editableTextKey);
|
||||
await tester.tap(textFinder);
|
||||
await tester.pump();
|
||||
|
||||
assert(focusNode.hasFocus);
|
||||
|
||||
// The execution path starting with receiveAction() will trigger the
|
||||
// onEditingComplete and onSubmission callbacks.
|
||||
await tester.testTextInput.receiveAction(TextInputAction.newline);
|
||||
|
||||
// These callbacks shouldn't have been triggered.
|
||||
assert(!onSubmittedCalled);
|
||||
assert(!onEditingCompleteCalled);
|
||||
});
|
||||
|
||||
testWidgets('Changing controller updates EditableText',
|
||||
(WidgetTester tester) async {
|
||||
final GlobalKey<EditableTextState> editableTextKey =
|
||||
|
Loading…
x
Reference in New Issue
Block a user