On my Windows App ( The interface looks like this: https://i.sstatic.net/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.