如何在Flutter中完全取消TextField的焦点而不会重新获得焦点?

9
在我的Flutter应用中,我有一个文本框,我希望能够通过点击非交互组件来将焦点从中移除。这不是Flutter中文本框的默认行为,因此我需要找到一种手动实现的方法。我已经按照https://flutterigniter.com/dismiss-keyboard-form-lose-focus/和其他网页上的步骤进行了一些操作,其中包括在根节点上使用一个具有onTap属性的GestureDetector,代码如下:
onTap: () {
  FocusScopeNode cf = FocusScope.of(context);
  if (!cf.hasPrimaryFocus && cf.focusedChild != null) {
    cf.focusedChild.unfocus();
    cf.unfocus();
  }
}

问题在于当我选择文本字段并单击其他地方(此时焦点似乎消失),打开时间选择器,然后关闭该时间选择器时,文本字段会重新获得焦点。如果我通过点击键盘上的“完成”按钮取消文本字段的焦点,那么打开/关闭时间选择器就不会重新聚焦文本字段,因此我知道这必须是因为我取消焦点的方式有问题。有什么正确的方法可以取消焦点,使焦点不会再次回来呢?
3个回答

18

我搞清楚了,看起来我需要在根部的GestureDetector中使用onTap: () => FocusManager.instance.primaryFocus.unfocus()。 我相当确定这是解决这个特定问题的最佳方案,尽管我不确定它是否会引起副作用。


3
unfocus 对我起作用,但 GestureDetector 只有在没有其他东西捕捉到点击时才会捕捉它。因此,屏幕上的任何其他按钮也必须调用 unfocus。 - spekary
@spekary,你解决了上面评论中提到的问题吗? - Hardik

9

使用GestureDetector包装整个屏幕,有两种方法可以关闭键盘。

  1. FocusScope.of(context).requestFocus(FocusNode());
import 'package:flutter/services.dart';

SystemChannels.textInput.invokeMethod('TextInput.hide');

所以请使用这段代码进行尝试

import 'package:flutter/services.dart';
onTap(){
    SystemChannels.textInput.invokeMethod('TextInput.hide');
   }

我已经尝试过 FocusScope.of(context).requestFocus(FocusNode());,但在打开时间选择器后焦点仍然会回到原来的位置。使用 SystemChannels 方法也无法解决问题,它只是隐藏了键盘而没有移除焦点,当我打开时间选择器时键盘又会出现。 - Lionel Foxcroft

2

对我而言,不需要调用unfocus方法就能正常工作的方法是告诉TextField本身不要自行请求焦点。 在文本字段本身中,我添加了以下内容:

focusNode: FocusNode(canRequestFocus: false),

我相信这是处理它的正确方式。


1
FocusNode 必须作为状态变量创建,并且必须被正确处理。 - TheSpixxyQ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接