How to focus the next field?

59 views Asked by At

I have a page with several text fields, I used FocusTraversalGroup so the fields are focused in the desired order when pressing tab. See:

With tab

Now, when I click on the icon button next, I want to send the focus to the next field. For example, if I click on the icon button next of the text field 3, I want the text field 4 to be focused. For that, I tried to use focusNode.nextFocus(), but the focus is sent to the text field 1 instead.

See the video:

click on next

Here is my code:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: Row(
          children: [
            Expanded(
              child: FocusTraversalGroup(
                child: Column(
                  children: <Widget>[
                    TextFormField(
                      decoration: const InputDecoration(label: Text('1')),
                    ),
                    TextFormField(
                      decoration: const InputDecoration(label: Text('2')),
                    ),
                    const _Field(
                      decoration: InputDecoration(label: Text('3')),
                    ),
                    TextFormField(
                      decoration: const InputDecoration(label: Text('4')),
                    ),
                    TextFormField(
                      decoration: const InputDecoration(label: Text('5')),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(width: 20),
            Expanded(
              child: FocusTraversalGroup(
                child: Column(
                  children: <Widget>[
                    TextFormField(
                      decoration: const InputDecoration(label: Text('6')),
                    ),
                    TextFormField(
                      decoration: const InputDecoration(label: Text('7')),
                    ),
                    const _Field(
                      decoration: InputDecoration(label: Text('8')),
                    ),
                    TextFormField(
                      decoration: const InputDecoration(label: Text('9')),
                    ),
                    TextFormField(
                      decoration: const InputDecoration(label: Text('10')),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _Field extends StatefulWidget {
  const _Field({
    this.decoration,
  });

  final InputDecoration? decoration;

  @override
  State<_Field> createState() => __FieldState();
}

class __FieldState extends State<_Field> {
  final focusNodeText = FocusNode();
  final focusNodeButton = FocusNode();

  @override
  void dispose() {
    focusNodeText.dispose();
    focusNodeButton.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return FocusTraversalGroup(
      child: Stack(
        children: [
          TextFormField(
            decoration: widget.decoration,
            focusNode: focusNodeText,
          ),
          Positioned(
            right: 0,
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                IconButton(
                  focusNode: focusNodeButton,
                  icon: const Icon(Icons.skip_next),
                  onPressed: () {
                    focusNodeButton.nextFocus();
                  },
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

What am I missing?

1

There are 1 answers

3
Munsif Ali On

you can call FocusScope.of(context).requestFocus(nextFocus); with onPressed of the icon like this:

IconButton(
                  focusNode: focusNodeButton,
                  icon: const Icon(Icons.skip_next),
                  onPressed: () {
                  FocusScope.of(context).requestFocus(nextFocus); //nextFocus is the focusNode to which you want to give focus. you have to assign this focus node that textField 
                  },
                ),