How to shift focus to next textfield in flutter?
Screenshot:
You can do that without using FocusNode
or FocusScopeNode
.
@override
Widget build(BuildContext context) {
final node = FocusScope.of(context);
return Scaffold(
body: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(hintText: 'TextField A'),
textInputAction: TextInputAction.next,
onEditingComplete: () => node.nextFocus(), // Move focus to next
),
TextField(
decoration: InputDecoration(hintText: 'TextField B'),
textInputAction: TextInputAction.next,
onEditingComplete: () => node.nextFocus(), // Move focus to next
),
TextField(
decoration: InputDecoration(hintText: 'TextField C'),
textInputAction: TextInputAction.done,
onSubmitted: (_) => node.unfocus(), // Submit and hide keyboard
),
],
),
);
}
Found a way to achieve it.
Displaying Next Icon instead of Done - setting
textInputAction
parameter toTextInputAction.next
Using
onFieldSubmitted
callback to request focus node of next field.class FormWidget extends StatelessWidget{ final focus = FocusNode(); @override Widget build(BuildContext context) { return Form( child: SingleChildScrollView( padding: EdgeInsets.symmetric(horizontal: 16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ TextFormField( textInputAction: TextInputAction.next, autofocus: true, decoration: InputDecoration(labelText: "Input 1"), onFieldSubmitted: (v){ FocusScope.of(context).requestFocus(focus); }, ), TextFormField( focusNode: focus, decoration: InputDecoration(labelText: "Input 2"), ), ], ), ), ); } }
Edit: As stated in the documentation (flutter.io/docs/cookbook/forms/focus), - we also need to manage FocusNode lifecycle. So, init FocusNode in the init() method and dispose in dispose() of the parent Widget. - @AntonDerevyanko
Update: The same can be achieved without FocusNode
and FocusScopeNode
, by simply calling FocusScope.of(context).nextFocus()
, take a look at CopsOnRoad solution on how to do that. For more info check doc.
This is additional steps to CopsOnRoad answer since it doesn't work in more complex UI when there are focusable widgets in between text fields, for example:
- when password field has a clickable toggle icon
- when there is a button(or some other focusable widget) between fields...
The solution here is to keep calling 'nextFocus()' until 'EditableText' is Found
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(hintText: "TextField A"),
textInputAction: textInputAction1,
onSubmitted: (_) => context.nextEditableTextFocus(), // move focus to next
),
TextField(
decoration: InputDecoration(hintText: "TextField B"),
textInputAction: textInputAction2,
onSubmitted: (_) => context.nextEditableTextFocus(), // move focus to next
),
MaterialButton(
onPressed: () {},
color: Colors.amber,
),
TextField(
decoration: InputDecoration(hintText: "TextField C"),
textInputAction: textInputAction3,
onSubmitted: (_) => FocusScope.of(context).unfocus(), // submit and hide keyboard
),
],
),
);
}
where the extension method is:
extension Utility on BuildContext {
void nextEditableTextFocus() {
do {
FocusScope.of(this).nextFocus();
} while (FocusScope.of(this).focusedChild.context.widget is! EditableText);
}
}