How to Move Focus to the Next TextField in Flutter

Build smooth, keyboard-friendly Flutter forms: move focus to the next TextField automatically using FocusNode, textInputAction, and onFieldSubmitted.

T

Teammity Team

· 1 min read

Nothing makes a mobile form feel clunky faster than having to tap every field by hand. Users expect the keyboard's Next button to jump to the next field and Done to submit. In Flutter that takes just a few lines once you know which pieces to use.

The two approaches

  1. FocusScope.of(context).nextFocus(): the quickest option; moves to the next focusable widget in order.
  2. FocusNode per field: explicit control over exactly which field gets focus next.

We will look at both.

Approach 1: nextFocus() for simple forms

Set textInputAction so the keyboard shows a Next button, and move focus when it is pressed:

TextField(
  decoration: const InputDecoration(labelText: 'Name'),
  textInputAction: TextInputAction.next,
  onSubmitted: (_) => FocusScope.of(context).nextFocus(),
),
TextField(
  decoration: const InputDecoration(labelText: 'Email'),
  keyboardType: TextInputType.emailAddress,
  textInputAction: TextInputAction.done,
),

Approach 2: FocusNode for full control

When fields are not in a simple top-to-bottom order, or you want to jump somewhere specific, give each field its own FocusNode:

lib/screens/signup_form.dart
class SignupForm extends StatefulWidget {
  const SignupForm({super.key});
 
  @override
  State<SignupForm> createState() => _SignupFormState();
}
 
class _SignupFormState extends State<SignupForm> {
  final _emailFocus = FocusNode();
  final _passwordFocus = FocusNode();
 
  @override
  void dispose() {
    // FocusNodes hold resources; always dispose them.
    _emailFocus.dispose();
    _passwordFocus.dispose();
    super.dispose();
  }
 
  void _submit() {
    FocusScope.of(context).unfocus(); // hide the keyboard
    // ...validate and send the form
  }
 
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextFormField(
          decoration: const InputDecoration(labelText: 'Name'),
          textInputAction: TextInputAction.next,
          onFieldSubmitted: (_) => _emailFocus.requestFocus(),
        ),
        TextFormField(
          focusNode: _emailFocus,
          decoration: const InputDecoration(labelText: 'Email'),
          keyboardType: TextInputType.emailAddress,
          textInputAction: TextInputAction.next,
          onFieldSubmitted: (_) => _passwordFocus.requestFocus(),
        ),
        TextFormField(
          focusNode: _passwordFocus,
          decoration: const InputDecoration(labelText: 'Password'),
          obscureText: true,
          textInputAction: TextInputAction.done,
          onFieldSubmitted: (_) => _submit(),
        ),
      ],
    );
  }
}

The last field uses TextInputAction.done and submits the form directly, so the user never has to reach for the button.

Bonus: dismiss the keyboard by tapping outside

Wrap the screen so tapping empty space closes the keyboard:

GestureDetector(
  onTap: () => FocusScope.of(context).unfocus(),
  child: Scaffold(/* your form */),
)

Wrapping up

  • Use textInputAction to show the right keyboard button.
  • Use nextFocus() for simple forms, or a FocusNode per field when you need precise control.
  • Submit on the last field and dispose your FocusNodes.

Small details like these are what make an app feel polished. Watch the full walkthrough in the video above, and see more Flutter tutorials.

Keep reading