Commit d556d211 authored by Francisco Magdaleno's avatar Francisco Magdaleno Committed by Greg Spencer

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
parent ffa8a1eb
......@@ -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 =
......
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