如何在flutter中将焦点转移到下一个文本字段?

时间:2018-09-03 13:23:52

标签: dart flutter flutter-layout

我是Flutter的新手。

我正在使用以下窗口小部件构建具有多个文本输入的表单:Form,TextFormField。出现的键盘不显示“下一个”(应将焦点移至下一个字段)字段操作,而是“完成”操作(隐藏键盘)。

我在官方文档中寻找任何提示,没有发现直接可以做的事情。 我虽然登陆了FocusNode(cookbookapi doc)。它提供了一种机制,可以通过应用程序上的某些按钮或其他任何操作来转移焦点,但我希望它位于键盘中。

8 个答案:

答案 0 :(得分:102)

截屏:

enter image description here


您可以不使用jobs: variables: changedcode: "" - job: steps: - powershell: | #Get the changed code folder with rest api - job: Infra condition: containsValue($(changedcode), "Infra")) - powershell: | #queue Infra pipeline with rest api or Trigger Azure DevOps Pipeline task - job: Deploy condition: (containsValue($(changedcode), "deploy")),and .... - powershell: | #queue Deploy pipeline with rest api or Trigger Azure DevOps Pipeline task FocusNode来做到这一点。

FocusScopeNode

答案 1 :(得分:11)

找到一种实现方法。

  1. 显示下一个图标而不是完成-将textInputAction参数设置为TextInputAction.next

  2. 使用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"),
                ),
              ],
            ),
          ),
        );
      }
    }
    

编辑:如文档(flutter.io/docs/cookbook/forms/focus)中所述,-我们还需要管理FocusNode生命周期。因此,请使用init()方法中的init FocusNode并将其放置在父Widget的dispose()中。 -@AntonDerevyanko

答案 2 :(得分:8)

这是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
            ),
          ],
        ),
      );
    }

扩展方法为:

extension Utility on BuildContext {
  void nextEditableTextFocus() {
    do {
      FocusScope.of(this).nextFocus();
    } while (FocusScope.of(this).focusedChild.context.widget is! EditableText);
  }
}

答案 3 :(得分:5)

对于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
        ),

答案 4 :(得分:5)

我尝试只添加 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',
            ),
          )
        ],
      ),
    );
  }
}

答案 5 :(得分:4)

对我而言,此方法有效,输入第一个数字时移至下一个输入

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(),
                          ),
                    )
                  ],
                )

答案 6 :(得分:1)

我用过 onSubmitted代替onFieldSubmitted

示例代码

      TextField(
                textInputAction: TextInputAction.next,
                onSubmitted: (_) => FocusScope.of(context).nextFocus(),
                controller: _phoneController,
                decoration: const InputDecoration(
                  labelText: 'Phone number',
                ),
                style: TextStyle(fontSize: 16.0, color: Colors.white),
              ),

答案 7 :(得分:0)

您可以使用此帮助器功能聚焦下一个文本字段:

void focusNextTextField(BuildContext context) {
  do {
    var foundFocusNode = FocusScope.of(context).nextFocus();
    if (!foundFocusNode) return;
  } while (FocusScope.of(context).focusedChild.context.widget is! EditableText);
}