简体   繁体   中英

Tab order in flutter

On my Windows App ( The interface looks like this: https://i.stack.imgur.com/SibAC.png )

When I focused to Input-1, and I press Tab key on keyboard, the primary focus will focus to Input-3. Is there any way to re-arrange my focus order: Input-1 -> Input-2 -> Input-3 -> Input-4 -> Input-5.

Attention: This is not Tab bar/tab controller in flutter's docs example.

This is my code:

3 files is in same root

main.dart

import 'package:flutter/material.dart';
import 'tab1.dart';
import 'tab2.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Tab oder',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Tab order'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final TextEditingController _controller = TextEditingController();
  final FocusNode _focusNode = FocusNode();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Form(
        key: GlobalKey<FormState>(),
        onChanged: () {
          Form.of(primaryFocus!.context!)!.save();
        },
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            Container(
              constraints: const BoxConstraints.tightFor(width: 200.0, height: 200.0),
              child: TextFormField(
                controller: _controller,
                focusNode: _focusNode,
                decoration: const InputDecoration(
                  filled: true,
                  fillColor: Colors.yellow,
                ),
              ),
            ),
            const SizedBox(width: 150.0),
            Column(
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                Container(
                  constraints: const BoxConstraints.tightFor(width: 200.0, height: 120.0),
                  child: Tab1(),
                ),
                Container(
                  constraints: const BoxConstraints.tightFor(width: 200.0, height: 120.0),
                  child: Tab2(),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

tab1.dart

import 'package:flutter/material.dart';

class Tab1 extends StatefulWidget {
  @override
  _Tab1State createState() => _Tab1State();
}

class _Tab1State extends State<Tab1> {
  final TextEditingController _controller1 = TextEditingController();
  final TextEditingController _controller2 = TextEditingController();
  final FocusNode _focusNode1 = FocusNode();
  final FocusNode _focusNode2 = FocusNode();

  @override
  build(BuildContext context) {
    return Column(
      children: [
        TextFormField(
          controller: _controller1,
          focusNode: _focusNode1,
          decoration: const InputDecoration(
            filled: true,
            fillColor: Colors.greenAccent,
          ),
        ),
        TextFormField(
          controller: _controller2,
          focusNode: _focusNode2,
          decoration: const InputDecoration(
            filled: true,
            fillColor: Colors.greenAccent,
          ),
        ),
      ],
    );
  }
}

tab2.dart

import 'package:flutter/material.dart';

class Tab2 extends StatefulWidget {
  @override
  _Tab2State createState() => _Tab2State();
}

class _Tab2State extends State<Tab2> {
  final TextEditingController _controller1 = TextEditingController();
  final TextEditingController _controller2 = TextEditingController();
  final FocusNode _focusNode1 = FocusNode();
  final FocusNode _focusNode2 = FocusNode();

  @override
  build(BuildContext context) {
    return Column(
      children: [
        TextFormField(
          controller: _controller1,
          focusNode: _focusNode1,
          decoration: const InputDecoration(
            filled: true,
            fillColor: Colors.greenAccent,
          ),
        ),
        TextFormField(
          controller: _controller2,
          focusNode: _focusNode2,
          decoration: const InputDecoration(
            filled: true,
            fillColor: Colors.greenAccent,
          ),
        ),
      ],
    );
  }
}

You can achieve the behavior you want via a FocusTraversalGroup , with this widget you specify the order in which you want the traversal to be performed.

This widgets takes a traversal policy as a parameter, I used a OrderedTraversalPolicy , but there are others like:

WidgetOrderTraversalPolicy , a policy that relies on the widget creation order to describe the order of traversal.

ReadingOrderTraversalPolicy , a policy that describes the order as the natural "reading order" for the current Directionality.

NumericFocusOrder, a focus order that assigns a numeric traversal order.

LexicalFocusOrder a focus order that assigns a string-based lexical traversal order.

Also there is an really interesting section about building adaptive apps in which focus and traversal order in different platforms is part of, you can check it out here

class Tab1 extends StatefulWidget {
  @override
  _Tab1State createState() => _Tab1State();
}

class _Tab1State extends State<Tab1> {
  final TextEditingController _controller1 = TextEditingController();
  final TextEditingController _controller2 = TextEditingController();
  final FocusNode _focusNode1 = FocusNode();
  final FocusNode _focusNode2 = FocusNode();

  @override
  build(BuildContext context) {
    return FocusTraversalGroup(
      policy: OrderedTraversalPolicy(),

If you need to change the traversal order of other groups(like tab2) simply wrap them in another FocusTraversalGroup and specify the policy you want them to follow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM