Just a little info about if this approach possible anyhow
I've been a developer in c# and vb.net winforms and there was a nice option of TabIndex
in almost every component or widget in this case in which we just need to write numbers and the system automatically handles the tabs (focus to next)/shift+tabs(focus to previous).
I understand flutter is made to achieve cross device (majorly for mobile devices if I am not wrong.) but I found this approach no where and on further search I found that this is not available in flutter. I mean even HTML has this TabIndex feature.
I've also seen AI generated code about using focusnode
and declaring each focusnode
for each textfield. I find this approach helpful but won't that be a lot tedious if I have approx 25 textfield in a single form/page/window?
Also I found this line of code FocusScope.of(context).nextFocus()
but how'd I let flutter know that I want to focus to 3rd textfield from 1st textfield and not 2nd textfield.
Also if I use shift + tab how can I get focus of previous focused tab?
So atlast a small summary,
What is want is
Note I don't know why I can't attach link above but this is link: How to shift focus to the next TextField in Flutter?
I hope moderators will edit it.
You can manipulate the order in which fields, buttons, etc, are focused by wrapping them in a FocusTraversalGroup
and supplying a FocusTraversalPolicy
.
FocusTraversalGroup(
policy: policy, // your FocusTraversalPolicy here
child: ..., // the objects you want to focus go in the child subtree
),
There are a few different policies you can choose from:
If you want to supply a specific numeric order for each focusable item, then you want OrderedTraversalPolicy
. With this policy you must also wrap each item you want to focus with a FocusTraversalOrder
widget.
FocusTraversalOrder(
order: NumericFocusOrder(order), // the focus order it should appear in the group
child: ..., // button or field you want to focus
),
I have put together a small demo that you can use to try out the different focus policies.
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(
title: 'Focus Demo',
home: FocusPage(),
));
}
class FocusPage extends StatefulWidget {
const FocusPage({super.key});
@override
State<FocusPage> createState() => _FocusPageState();
}
FocusTraversalPolicy orderedTraversalPolicy = OrderedTraversalPolicy();
FocusTraversalPolicy readingTraversalPolicy = ReadingOrderTraversalPolicy();
FocusTraversalPolicy widgetTraversalPolicy = WidgetOrderTraversalPolicy();
class _FocusPageState extends State<FocusPage> {
List<List<({String name, double order})>> fields = [
[
(name: 'A', order: 4),
(name: 'B', order: 2),
(name: 'C', order: 6),
],
[
(name: 'D', order: 3),
(name: 'E', order: 5),
(name: 'F', order: 1),
],
];
FocusTraversalPolicy? policy = orderedTraversalPolicy;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Focus Demo'),
actions: [
FocusTraversalGroup(
descendantsAreTraversable: false,
child: DropdownButton<FocusTraversalPolicy>(
value: policy,
items: [
DropdownMenuItem(
value: orderedTraversalPolicy,
child: const Text('Custom Order'),
),
DropdownMenuItem(
value: readingTraversalPolicy,
child: const Text('Reading Order'),
),
DropdownMenuItem(
value: widgetTraversalPolicy,
child: const Text('Widget Order'),
),
],
onChanged: (v) {
setState(() {
policy = v;
});
},
),
),
],
),
body: FocusTraversalGroup(
policy: policy,
child: Row(
children: [
for (var row in fields)
Expanded(
child: Column(
children: [
for (var (:name, :order) in row)
Expanded(
child: Padding(
padding: const EdgeInsets.all(25),
child: FocusTraversalOrder(
order: NumericFocusOrder(order),
child: TextField(
decoration: InputDecoration(
labelText: name,
),
),
),
),
),
],
),
),
],
),
),
);
}
}