You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter TextFormField焦点异常:点击发送后键盘无法重复唤起

解决Flutter点击发送按钮后键盘无法重复唤起的问题

问题背景

需求:点击发送按钮时保持键盘处于打开/聚焦状态,不关闭。
当前问题:首次点击发送按钮时,键盘关闭后通过focusNode.requestFocus()能重新唤起,但再次点击后键盘无法打开。经追踪发现,第二次调用时焦点管理器中以下条件始终为true,导致代码直接返回,未尝试唤起键盘:

if (hasPrimaryFocus && (_manager!._markedForFocus == null || _manager!._markedForFocus == this)) {

尽管键盘已关闭,但焦点节点仍被标记为拥有主焦点,无法触发重新聚焦逻辑。


解决方案1(最优):点击发送按钮时不让键盘关闭

核心思路:避免主动隐藏键盘,同时确保发送操作不会夺走输入框的焦点。

修改UI代码

移除SystemChannels.textInput.invokeMethod('TextInput.hide'),并给按钮添加跳过焦点遍历的配置,防止抢占输入框焦点:

return Form(
  key: _formKey,
  child: Row(
    children: <Widget>[
      Expanded(
        child: TextFormField(
          focusNode: chatController.focusNode,
          // 可选:设置回车触发发送,提升交互体验
          textInputAction: TextInputAction.send,
          onFieldSubmitted: (_) async {
            if (_formKey.currentState!.validate()) {
              await chatController.sendMessage(context);
            }
          },
        ),
      ),
      IconButton(
        // 跳过焦点遍历,防止按钮抢占输入框焦点
        focusNode: FocusNode(skipTraversal: true),
        icon: const Icon(Icons.send),
        onPressed: () async {
          // 移除主动隐藏键盘的代码
          if (_formKey.currentState!.validate()) {
            await chatController.sendMessage(context);
          }
        },
      ),
    ],
  ),
);

修改控制器代码

无需额外处理焦点,发送逻辑执行完成后输入框会自动保持焦点:

late FocusNode focusNode;

@override
void onReady() {
  focusNode = FocusNode();
  super.onReady();
}

void sendMessage(BuildContext context) async {
  // 执行你的消息发送逻辑
  // ...
  
  // 若有清空输入框操作,无需额外调用requestFocus,焦点仍会保留
  // textEditingController.clear();
}

解决方案2(可行):确保每次点击都能唤起键盘

如果业务需要先隐藏键盘再唤起(比如清空输入框后重新聚焦),可以通过先强制取消焦点,再延迟请求焦点的方式绕过焦点管理器的判断逻辑。

修改控制器代码

late FocusNode focusNode;

@override
void onReady() {
  focusNode = FocusNode();
  super.onReady();
}

void sendMessage(BuildContext context) async {
  // 1. 强制取消焦点,标记节点为失焦状态
  focusNode.unfocus();
  // 2. 短暂延迟,确保焦点状态完成更新
  await Future.delayed(const Duration(milliseconds: 100));
  // 3. 重新请求焦点,唤起键盘
  focusNode.requestFocus();
  
  // 执行你的消息发送逻辑
  // ...
}

修改UI代码

可选择保留或移除TextInput.hide,上述逻辑会强制重新唤起键盘:

IconButton(
  icon: const Icon(Icons.send),
  onPressed: () async {
    // 可选:如果需要先隐藏键盘再唤起
    // SystemChannels.textInput.invokeMethod('TextInput.hide');
    if (_formKey.currentState!.validate()) {
      await chatController.sendMessage(context);
    }
  },
),

内容的提问来源于stack exchange,提问作者Navnav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 10:20:42