Har*_*dia 10 dart flutter flutter-layout
我是Flutter的新手.
我正在使用以下小部件构建具有多个文本输入的表单:Form,TextFormField.出现的键盘不会显示"next"(应该将焦点移到下一个字段)字段操作,而是"完成"操作(隐藏keyborad).
我寻找官方文档中的任何提示,没有直接发现可以做到的事情.我虽然登陆了FocusNode(cookbook,api doc).它提供了通过某个按钮或应用程序上的任何其他操作来移动焦点的机制,但我希望它在键盘中.
Cop*_*oad 177
截屏:
只需使用:
textInputAction: TextInputAction.next:将光标移动到下一个字段。
textInputAction: TextInputAction.done: 关闭键盘。
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(hintText: 'TextField A'),
textInputAction: TextInputAction.next, // Moves focus to next.
),
TextField(
decoration: InputDecoration(hintText: 'TextField B'),
textInputAction: TextInputAction.next, // Moves focus to next.
),
TextField(
decoration: InputDecoration(hintText: 'TextField C'),
textInputAction: TextInputAction.done, // Hides the keyboard.
),
],
),
);
}
Run Code Online (Sandbox Code Playgroud)
Har*_*dia 27
找到了实现它的方法.
显示下一个图标而不是完成 - 将textInputAction参数设置为TextInputAction.next
使用onFieldSubmitted回调来请求下一个字段的焦点节点.
class FormWidget extends StatelessWidget{
final focus = FocusNode();
@override
Widget build(BuildContext context) {
return Form(
child: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextFormField(
textInputAction: TextInputAction.next,
autofocus: true,
decoration: InputDecoration(labelText: "Input 1"),
onFieldSubmitted: (v){
FocusScope.of(context).requestFocus(focus);
},
),
TextFormField(
focusNode: focus,
decoration: InputDecoration(labelText: "Input 2"),
),
],
),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)编辑:如文档(flutter.io/docs/cookbook/forms/focus)中所述,我们还需要管理FocusNode生命周期.因此,在init()方法中初始化FocusNode并将其置于父Widget的dispose()中. - @AntonDerevyanko
Hay*_*mar 21
这是CopsOnRoad答案的附加步骤,因为当文本字段之间存在可聚焦小部件时,它在更复杂的 UI 中不起作用,例如:
这里的解决方案是继续调用“nextFocus()”直到找到“EditableText”
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(hintText: "TextField A"),
textInputAction: textInputAction1,
onSubmitted: (_) => context.nextEditableTextFocus(), // move focus to next
),
TextField(
decoration: InputDecoration(hintText: "TextField B"),
textInputAction: textInputAction2,
onSubmitted: (_) => context.nextEditableTextFocus(), // move focus to next
),
MaterialButton(
onPressed: () {},
color: Colors.amber,
),
TextField(
decoration: InputDecoration(hintText: "TextField C"),
textInputAction: textInputAction3,
onSubmitted: (_) => FocusScope.of(context).unfocus(), // submit and hide keyboard
),
],
),
);
}
Run Code Online (Sandbox Code Playgroud)
其中扩展方法是:
extension Utility on BuildContext {
void nextEditableTextFocus() {
do {
FocusScope.of(this).nextFocus();
} while (FocusScope.of(this).focusedChild.context.widget is! EditableText);
}
}
Run Code Online (Sandbox Code Playgroud)
对于 TextFormFeild 使用可以使用 onFieldSubmitted
TextFormField(
decoration: InputDecoration(hintText: "Username"),
textInputAction: TextInputAction.next,
onFieldSubmitted: (_) => FocusScope.of(context).nextFocus(), // focus to next
),
TextFormField(
decoration: InputDecoration(hintText: "Password"),
textInputAction: TextInputAction.done,
onFieldSubmitted: (_) => FocusScope.of(context).unfocus(), // Unfocus and hide keyboard
),
Run Code Online (Sandbox Code Playgroud)
不知道确切原因,但 onFieldSubmitted 有时会跳过一个或多个字段,在这种情况下 onEditingComplete 按预期工作
TextFormField(
decoration: InputDecoration(hintText: "Username"),
textInputAction: TextInputAction.next,
onEditingComplete : (_) => FocusScope.of(context).nextFocus(), // focus to next
),
TextFormField(
decoration: InputDecoration(hintText: "Password"),
textInputAction: TextInputAction.done,
onEditingComplete : (_) => FocusScope.of(context).unfocus(), // Unfocus and hide keyboard
),
Run Code Online (Sandbox Code Playgroud)
对我来说,这行得通,它在输入第一个数字时移动到下一个输入
Row(
children: <Widget>[
Expanded(
child: TextFormField(
textInputAction: TextInputAction.next,
onChanged: (_) => FocusScope.of(context).nextFocus(),
controller:c1 ,)
),
SizedBox(
width: 20.0,
),
Expanded(
child: TextFormField(
textInputAction: TextInputAction.next,
onChanged: (_) => FocusScope.of(context).nextFocus(),
controller:c2 ,),
),
SizedBox(
width: 20.0,
),
Expanded(
child: TextFormField(
controller:c3 ,
textInputAction: TextInputAction.next,
onChanged: (_) => FocusScope.of(context).nextFocus(),),
),
SizedBox(
width: 20.0,
),
Expanded(
child: TextFormField(
controller:c4 ,
textInputAction: TextInputAction.next,
onChanged: (_) => FocusScope.of(context).nextFocus(),),
),
SizedBox(
width: 20.0,
),
Expanded(
child: TextFormField(
controller:c5 ,
textInputAction: TextInputAction.next,
onChanged: (_) => FocusScope.of(context).nextFocus(),),
),
SizedBox(
width: 20.0,
),
Expanded(
child: TextFormField(
controller:c6 ,
textInputAction: TextInputAction.next,
onChanged: (_) => FocusScope.of(context).unfocus(),
),
)
],
)
Run Code Online (Sandbox Code Playgroud)
小智 9
感谢 @haytham-anmar 分享的扩展和 @natesh-bhat 的扩展!
但由于树上的重大更改,这对于 Flutter 的未来版本将不再起作用EditableText(参考:将文本编辑操作移至 EditableTextState #90684)。
请考虑以下迁移代码:
迁移前:
extension Utility on BuildContext {
void nextEditableTextFocus() {
do {
FocusScope.of(this).nextFocus();
} while (FocusScope.of(this).focusedChild?.context?.widget is! EditableText);
}
}
Run Code Online (Sandbox Code Playgroud)
迁移后:
extension Utility on BuildContext {
void nextEditableTextFocus() {
do {
FocusScope.of(this).nextFocus();
} while (FocusScope.of(this).focusedChild!.context == null);
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试只添加textInputAction属性,它没有其他任何东西。
也许新版本的 Flutter 改进了这个功能?或者需要 StatefulWidget 和 FormKey 才能正常工作?
我在 Flutter 上(通道稳定,1.22.5)
试一试:
class MyForm extends StatefulWidget {
@override
State createState() => _myFormState();
}
class _myFormState extends State<MyForm> {
//
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
// *** Just added this
textInputAction: TextInputAction.next,
decoration: const InputDecoration(
labelText: 'Input 1',
),
),
TextFormField(
textInputAction: TextInputAction.done,
decoration: const InputDecoration(
labelText: 'Input 2',
),
)
],
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8252 次 |
| 最近记录: |