Flutter-FocusNode-为什么requestFocus()无法正常工作?

时间:2019-05-20 13:07:30

标签: flutter

以下是相关代码。 onFieldSubmitted:中的debugPrint()正在运行,因此代码正在到达此处,但是焦点没有改变。焦点不会改变。

 _createItemHeadingWidget() {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: TextFormField(
        controller: _controllerItemHed,
        autofocus: true,
        focusNode: _focusNodeItemHed,
        textInputAction: TextInputAction.next,
        onFieldSubmitted: (v) {
          debugPrint("ItemHeading submitted");
          FocusScope.of(context).requestFocus(_focusNodeItemDetail);
        },
        decoration: InputDecoration(
          labelText: "Item Heading",
          hintText: "Enter item heading",
          border: OutlineInputBorder(borderRadius: BorderRadius.circular(20.0)),
        ),
      ),
    );
  }
  Widget _createItemDetailWidget() {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: TextFormField(
        controller: _controllerItemDetail,
        maxLength: 75,
        focusNode: _focusNodeItemDetail,
        textInputAction: TextInputAction.next,
        onFieldSubmitted: (v) {
          debugPrint("ItemDetail submitted");
          FocusScope.of(context).requestFocus(_focusNodeItemPrice);
        },
        decoration: InputDecoration(
          labelText: "Item Detail",
          hintText: "Enter item detail",
          border: OutlineInputBorder(borderRadius: BorderRadius.circular(20.0)),
        ),
      ),
    );
  }
class DataEntryState extends State<DataEntry> {
  final TextEditingController _controllerItemHed = TextEditingController();
  final TextEditingController _controllerItemDetail = TextEditingController();
  final TextEditingController _controllerItemPrice = TextEditingController();
  final TextEditingController _controllerSeller = TextEditingController();
  final TextEditingController _controllerContactNr = TextEditingController();
  final TextEditingController _controllerLocation = TextEditingController();

  final FocusNode _focusNodeItemHed = FocusNode();
  final FocusNode _focusNodeItemDetail = FocusNode();
  final FocusNode _focusNodeItemPrice = FocusNode();
  final FocusNode _focusNodeSeller = FocusNode();
  final FocusNode _focusNodeContactNr = FocusNode();
  final FocusNode _focusNodeLocation = FocusNode();

8 个答案:

答案 0 :(得分:0)

尝试了许多无效的方法后,我能找到的唯一解决方案如下:

  _changeFocus(BuildContext context, FocusNode focusNodeCurrent,
      FocusNode focusNodeNext) {
    focusNodeCurrent.unfocus();
    setState(() => _focusNodeCurrent = focusNodeNext);
  }

debugPrint()表明,在_changeFocus()中,unfocus()有效,而requestFocus()不起作用。

在构建中:

    if (_focusNodeCurrent != null)
      FocusScope.of(context).requestFocus(_focusNodeCurrent);

其他相关代码(其中一些可能是多余的):

 TextFormField _createItemHeadingWidget(BuildContext context) {
    FocusScope.of(context).reparentIfNeeded(_focusNodeItemHed);
    return TextFormField(
      controller: _controllerItemHed,
      maxLength: 50,
      keyboardType: TextInputType.text,
      autofocus: _dataRec == null,
      focusNode: _focusNodeItemHed,
      textInputAction: TextInputAction.next,
      onFieldSubmitted: (v) {
        _changeFocus(context, _focusNodeItemHed, _focusNodeItemDetail);
      },
      decoration: InputDecoration(
        labelText: "Item Heading",
        hintText: "Enter item heading",
        border: OutlineInputBorder(borderRadius: BorderRadius.circular(20.0)),
      ),
    );
  }

答案 1 :(得分:0)

使用setState()解决此问题对我来说似乎不是最佳解决方案,因此我一直进行测试。经过大量的进一步测试,主要涉及从应用程序中删除所有可能的东西之后,我最终用创建Scaffold代替了MaterialApp的创建。这解决了问题。现在,它似乎可以正常工作。所需要做的就是:

 _changeFocus(BuildContext context, FocusNode focusNodeNew) {
    FocusScope.of(context).requestFocus(focusNodeNew);
  }

我认为最初创建MaterialApp的原因是,当我最初开始学习Flutter时,是从另一个应用程序复制了它。似乎没有必要创建MaterialApp,但是我不知道创建MaterialApp的原因,而不是仅仅创建Scaffold。

我不知道是否是颤振中的错误导致了这种现象。这可能只是使用MaterialApp的“功能”,或者可能是我滥用了MaterialApp。

答案 2 :(得分:0)

这很好地说明了颤振焦点的工作原理:https://flutter.dev/docs/cookbook/forms/focus

答案 3 :(得分:0)

对于其他为此感到挣扎的人,我只是在玩耍并制作了一个演示。

enter image description here

您可以将焦点切换到左侧或右侧文本字段或取消焦点。下面的代码是@Brian Oh的答案和一些新代码的组合。功能:

  • 保留所有节点的跟踪,包括无焦点和当前焦点
  • changeFocus函数仅需要nextFocus参数,不使用FocusScope.of(context).requestFocus(_nextFocusNode),也不必设置状态
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: Home(),);
  }
}

class Home extends StatefulWidget {
  @override
  HomeState createState() => HomeState();
}

class HomeState extends State<Home> {

  FocusNode currentFocusNode;
  FocusNode leftFocusNode;
  FocusNode rightFocusNode;
  FocusNode noFocusNode;

  @override
  void initState() {
    super.initState();
    currentFocusNode = FocusNode();
    leftFocusNode = FocusNode();
    rightFocusNode = FocusNode();
    noFocusNode = FocusNode();
  }

  @override
  void dispose() {
    //currentFocusNode.dispose();
    //leftFocusNode.dispose();
    //rightFocusNode.dispose();
    //noFocusNode.dispose();
    super.dispose();
  }

  changeFocus(FocusNode focusNodeNext) {
    currentFocusNode.unfocus();
    focusNodeNext.requestFocus();
    currentFocusNode = focusNodeNext;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.fromLTRB(0, 40, 0, 0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [

            Column(
              children: <Widget>[
                Container( width: 50, child: TextField(
                  focusNode: leftFocusNode,
                ),),
                RaisedButton(
                  child: Text('^ Focus ^'),
                  onPressed: () => changeFocus(leftFocusNode),
                ),
              ],
            ),

            Column(
              children: <Widget>[
                Container( width: 50, child: TextField(
                  focusNode: rightFocusNode,
                ),),
                RaisedButton(
                  child: Text('^ Focus ^'),
                  onPressed: () => changeFocus(rightFocusNode),
                ),
              ],
            ),

            RaisedButton(
              child: Text('  Cancel Focus'),
              onPressed: () => changeFocus(noFocusNode),
            ),

          ],
        ),
      ),
    );
  }
}

编辑:

我在另一个应用程序中使用了此代码,但出现了错误

在处理之后使用了FocusNode。

根据this github link,您不应调用Dispose。我已注释掉对上面的焦点节点进行的处理调用,并且错误消失了。

答案 4 :(得分:0)

使用

FocusScope.of(context).unfocus();

代替

FocusScope.of(context).requestFocus(new FocusNode());

答案 5 :(得分:0)

您可以通过在焦点更改中添加一些延迟来务实地更改焦点

FocusNode currentFocus = focusName.hasFocus? focusName : focusEmail;
FocusScope.of(context).unfocus();
Timer(const Duration(milliseconds: 1), () {
FocusScope.of(context).requestFocus(currentFocus);
});

答案 6 :(得分:0)

firstFieldFocusNode.nextFocus();

帮我搞定了

答案 7 :(得分:-1)

使用 FocusScope.of(context).nextFocus() 对我有用

我使用的自定义小部件代码

CupertinoTextFormFieldRow customTextField(
  String pretext, String supportText,
  TextEditingController controller, Function(String) validatorFun) {
  return CupertinoTextFormFieldRow(
    controller: controller,
    prefix: Text(pretext),
    placeholder: supportText,
    validator: (val) => validatorFun(val!),
    textInputAction: TextInputAction.next,
    onEditingComplete: () {
      FocusScope.of(context).nextFocus();
    },
  );
}```