当从一个焦点组遍历到下一个(键盘上的选项卡)时,我希望焦点移动到下一组中的第一个字段,但它似乎什么都不关注 - 然后另一个选项卡移动到该组中。
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
for (var i = 0; i < 2; i++)
FocusableActionDetector(
onFocusChange: (focused) {
if (!focused) {
print('Have left focus group');
}
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
for (var i = 0; i < 3; i++)
SizedBox(
width: 150,
child: TextField(),
),
],
),
),
],
),
),
),
);
}
}
Dartpad example我希望在第一组的最后一个字段之后按
Tab
应立即将焦点移至下一个焦点组中的第一个项目。我已经尝试了各种
FocusNode
, FocusScope
, FocusScope.of(context).___
,但是我发现 Flutter 中的焦点管理有点困惑。
最佳答案
前言:我不是Focus
的专家我自己也觉得很复杂。
但我相信以下内容适用于您所追求的内容,从一列遍历到下一列,而不聚焦“不可见”的项目 .至少在移动设备上。网络平台......这是一个完全不同的球赛(我怀疑它的工作原理是一样的)。
我摆脱了FocusableActionDetector
(它作为 FocusNode
本身)并将每个 Column 包裹在一个 FocusTraversalGroup
中.我相信 Flutter 会尽可能地从 TraversalGroup 转到 TraversalGroup。FocusScope
包装 TraversalGroups 可防止后退按钮和任何其他可点击项目获得焦点(一旦 FocusScope
获得焦点)。
class MyHomePage2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
width: double.infinity,
child: FocusScope( // LIMIT FOCUS TO DESCENDANTS
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
for (var i = 0; i < 2; i++)
FocusTraversalGroup( // CREATE GROUPS HERE
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
for (var i = 0; i < 3; i++)
SizedBox(
width: 150,
child: TextField(),
),
],
),
),
],
),
),
),
),
);
}
}
概括(据我所知,这是模糊的)
FocusScope
限制节点遍历到它的直接后代节点FocusScope
到另一个 FocusScope
FocusScope
用户将需要手动/单击聚焦另一个 FocusScope
,或其后代节点必须requestFocus
FocusScope
而不是 FocusTraversalGroup
以上,将节点遍历限制为一个 Column
,以得到焦点为准。它不会从一个 Column
跳转到达最后一个时到下一个 TextField
FocusTraversalGroup
将后代收集到一个组中进行遍历FocusTraversalGroup
时跳转有货 调试
使用
debugDumpFocusTree
转储焦点树(随处可用的静态函数)有助于调试。我有时会将它添加到 AppBar 以便于按需访问:
return Scaffold(
appBar: AppBar(
title: Text('Focus Tab Page'),
actions: [
IconButton(icon: Icon(Icons.info_outline), onPressed: debugDumpFocusTree)
],
),
我已复制到下面的相关部分。└─Child 2: FocusScopeNode#c83f0(_ModalScopeState<dynamic> Focus Scope [IN FOCUS PATH])
│ context: FocusScope
│ IN FOCUS PATH
│ focusedChildren: FocusScopeNode#7d536([IN FOCUS PATH])
│
├─Child 1: FocusScopeNode#7d536([IN FOCUS PATH])
│ │ context: FocusScope
│ │ IN FOCUS PATH
│ │ focusedChildren: FocusNode#1b886([PRIMARY FOCUS]),
│ │ FocusNode#72c3b, FocusNode#34b25, FocusNode#3b410,
│ │ FocusNode#02fac, FocusNode#61cd5
│ │
│ ├─Child 1: FocusNode#1d51e(FocusTraversalGroup)
│ │ │ context: Focus
│ │ │ NOT FOCUSABLE
│ │ │
│ │ ├─Child 1: FocusNode#3b410
│ │ │ context: EditableText-[LabeledGlobalKey<EditableTextState>#70699]
│ │ │
│ │ ├─Child 2: FocusNode#34b25
│ │ │ context: EditableText-[LabeledGlobalKey<EditableTextState>#7c822]
│ │ │
│ │ └─Child 3: FocusNode#72c3b
│ │ context: EditableText-[LabeledGlobalKey<EditableTextState>#f00bc]
│ │
│ └─Child 2: FocusNode#bdb17(FocusTraversalGroup [IN FOCUS PATH])
│ │ context: Focus
│ │ NOT FOCUSABLE
│ │ IN FOCUS PATH
│ │
│ ├─Child 1: FocusNode#1b886([PRIMARY FOCUS])
│ │ context: EditableText-[LabeledGlobalKey<EditableTextState>#c5a56]
│ │ PRIMARY FOCUS
│ │
│ ├─Child 2: FocusNode#61cd5
│ │ context: EditableText-[LabeledGlobalKey<EditableTextState>#a4dd8]
│ │
│ └─Child 3: FocusNode#02fac
│ context: EditableText-[LabeledGlobalKey<EditableTextState>#fe12d]
│
├─Child 2: FocusNode#4886e
│ context: Focus
│
└─Child 3: FocusNode#9241b
context: Focus
关于flutter - 如何立即切换焦点组(通过键盘)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67808972/