推送到包含该字段的路由后,将焦点放在 CupertinoTextField 上

flutter focus on a CupertinoTextField after pushing to the route which contains that field

我有一个基于选项卡的应用程序,每个选项卡都有多个导航堆栈(使用 CupertinoTabScaffold)

在我推送到具有以下字段的路线后,我试图专注于 CupertinoTextField:

屏幕 1:

Navigator.of(context).push(CupertinoPageRoute<void>(
  builder: (BuildContext context) => SearchResultPage(),
));

屏幕 2:

  @override
  void initState() {
    Timer(Duration(milliseconds: 1000), () {
      FocusScope.of(context).requestFocus(_focus);
    });
    super.initState();
  }

此代码有效,但如果我删除计时器,我会收到一条错误消息:

flutter: When an inherited widget changes, for example if the value of Theme.of() changes, its dependent
flutter: widgets are rebuilt. If the dependent widget's reference to the inherited widget is in a constructor
flutter: or an initState() method, then the rebuilt dependent widget will not reflect the changes in the
flutter: inherited widget.
flutter: Typically references to inherited widgets should occur in widget build() methods. Alternatively,
flutter: initialization based on inherited widgets can be placed in the didChangeDependencies method, which
flutter: is called after initState and whenever the dependencies change thereafter.

在 flutter 文档中为 initState 方法定义:

Override this method to perform initialization that depends on the location at which this object was inserted into the tree (i.e., context) or on the widget used to configure this object (i.e., widget).

这意味着此函数用于初始化,甚至在构建方法被调用之前运行,因此当您删除计时器时,您实际上是在尝试将焦点放在尚未 built/rendered 的小部件上根据框架。这就是错误的原因。

错误消息已经非常明确地说明了您需要做什么来解决这个问题:

  Timer _timer;

  @override
  void didChangeDependencies () {
    _timer = Timer(Duration(milliseconds: 1000), () {
      FocusScope.of(context).requestFocus(_focus);
    });
    super.didChangeDependencies();
  }

@override
void dispose() {
  _timer?.dispose();
  super.dispose();
}

您还需要确保正确丢弃此 Timer(如上例所示)。

但是还有一种更简单的方法来自动聚焦文本字段,如 cookbook:

中所述

To give focus to a text field as soon as it’s visible, use the autofocus property.

TextField(
  autofocus: true,
);

要专注于 CupertinoSearchTextField 渲染,您可以尝试这种方法 首先:

像这样创建一个焦点节点:

FocusNode node = FocusNode();

然后将其添加到您的 CupertinoSearchTextField

CupertinoSearchTextField(focusNode: node,)

然后在您的构建方法中,就在 return 调用

之前
Widget build(BuildContext context) {
FocusScope.of(context).requestFocus(node);
return CupertinoSearchTextField(focusNode: node,);
}

最后还包括处理 :

@override
void dispose() {
  node.dispose();
  super.dispose();
}

你准备好了..

这对我有用,超时时间短。

class _MyPageState extends State<MyPage> {
  FocusNode _node = FocusNode();

  // ....

  @override
  void initState() {
    super.initState();
    Future.delayed(Duration(milliseconds: 350)).then((_) {
      FocusScope.of(context).requestFocus(_node);
    });
  }

并根据需要将节点附加到您的文本小部件,例如:

CupertinoSearchTextField(
  focusNode: _node,
)