flutter FocusNode -为什么requestFocus()不工作?

7hiiyaii  于 2023-03-31  发布在  Flutter
关注(0)|答案(7)|浏览(413)

以下是相关代码。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();
dba5bblo

dba5bblo1#

在尝试了许多不起作用的事情之后,我能找到的唯一解决方案如下:

_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)),
      ),
    );
  }
r6vfmomb

r6vfmomb2#

使用

FocusScope.of(context).unfocus();

而不是

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

omjgkv6w3#

firstFieldFocusNode.nextFocus();

对我很管用

6ovsh4lw

6ovsh4lw4#

使用setState()来解决这个问题在我看来并不是最佳的解决方案,所以我继续测试。经过大量的进一步测试,主要包括从应用程序中删除所有我能删除的内容,我最终用创建Scaffold来替换MaterialApp的创建。这解决了这个问题。现在它看起来像预期的那样工作。所需要做的就是:

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

我认为我最初创建MaterialApp的原因是我最初开始学习Flutter时从另一个应用程序复制了它。似乎没有必要创建MaterialApp,但我不知道创建MaterialApp而不是只创建支架的原因。
是否是flutter中的bug导致了这种行为,我不知道。这可能只是使用MaterialApp的一个“特性”,也可能是我误用了MaterialApp。

dsf9zpds

dsf9zpds5#

对于其他任何人挣扎与此,我只是在玩,并作出了演示。

你可以将焦点切换到左边或右边的文本字段,或者取消焦点。下面的代码是@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。我已经注解掉了上面对焦点节点的dispose调用,错误消失了。

q5iwbnjs

q5iwbnjs6#

调用时使用此=〉

FocusNode _focusNodeItemDetail = FocusNode();

_changeFocus(){
    Future.delayed(Duration(milliseconds: 50),(){
             FocusScope.of(context).requestFocus(_focusNodeItemDetail);
    });
}
pqwbnv8z

pqwbnv8z7#

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

我使用的自定义Widget代码

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();
    },
  );
}```

相关问题