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

Flutter Bottom Sheet按返回键:键盘关闭但TextField仍聚焦的问题

解决方案:返回键关闭BottomSheet内TextField键盘并取消焦点

问题核心在于返回键事件的处理时机和焦点管理范围,你可以通过以下两种可靠方式解决:

方式一:用WillPopScope正确拦截返回事件

替换你当前的OnBackPressed组件为Flutter原生的WillPopScope,在返回触发时先全局清理焦点,再允许BottomSheet关闭:

showModalBottomSheet(
  context: context,
  isScrollControlled: true,
  builder: (context) {
    return StatefulBuilder(builder: (context, setModalState) {
      return WillPopScope(
        onWillPop: () async {
          // 全局取消所有焦点,确保TextField失去聚焦(比单个focusNode更稳妥)
          FocusManager.instance.primaryFocus?.unfocus();
          // 允许系统执行返回操作,关闭BottomSheet
          return true;
        },
        child: Container(
          padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
          child: TextField(
            focusNode: _focusNode,
            decoration: InputDecoration(
              hintText: 'Add comments...',
            ),
            textInputAction: TextInputAction.done,
            onEditingComplete: () async {
              _focusNode.unfocus();
              // 编辑完成后的其他逻辑
            },
          ),
        ),
      );
    });
  },
);

关键细节:

  • 使用FocusManager.instance.primaryFocus?.unfocus()替代单个_focusNode.unfocus(),可以覆盖所有可能的焦点场景,避免单个焦点节点失效的问题。
  • WillPopScope的onWillPop返回true,表示允许系统执行默认返回行为;如果需要先完成异步逻辑再关闭弹窗,也可以在这里添加await操作。

方式二:监听BottomSheet关闭事件清理焦点

如果第一种方式仍有异常,可以利用showModalBottomSheet的异步特性,在弹窗关闭后强制清理焦点:

void _showCommentBottomSheet() async {
  final result = await showModalBottomSheet(
    context: context,
    isScrollControlled: true,
    builder: (context) {
      return StatefulBuilder(builder: (context, setModalState) {
        return Container(
          padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
          child: TextField(
            focusNode: _focusNode,
            decoration: InputDecoration(
              hintText: 'Add comments...',
            ),
            textInputAction: TextInputAction.done,
            onEditingComplete: () async {
              _focusNode.unfocus();
              // 编辑完成后的其他逻辑
            },
          ),
        );
      });
    },
  );

  // 弹窗关闭后,强制清除焦点
  _focusNode.unfocus();
  // 或者用全局清理兜底
  FocusManager.instance.primaryFocus?.unfocus();
}

关键细节:

  • showModalBottomSheet是异步方法,弹窗关闭后会执行后续代码,这里处理焦点清理可以确保无论通过返回键还是其他方式关闭弹窗,都能清除TextField的焦点。

额外注意事项

  • 确保_focusNode在State类中正确初始化:final _focusNode = FocusNode();,并在组件dispose时调用_focusNode.dispose()避免内存泄漏。
  • 如果使用自定义OnBackPressed组件,需确认它没有拦截或覆盖返回事件的默认处理逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:58:17