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

Flutter:设置isDismissible:true时,点击模态屏障先关键盘再关底部弹窗

实现方案

核心思路是禁用默认的屏障关闭逻辑,手动接管屏障点击事件,同时通过Flutter原生API判断键盘状态,分情况执行「关闭键盘」或「关闭弹窗」操作。

1. 关键逻辑拆解

  • 把isDismissible设为false,取消默认的屏障点击关闭弹窗行为
  • 用barrierTapCallback自定义屏障点击后的处理逻辑
  • 通过MediaQuery.of(context).viewInsets.bottom判断键盘是否弹出:该值大于0时表示键盘处于显示状态
  • 调用FocusManager.instance.primaryFocus?.unfocus()关闭当前激活的软键盘

2. 完整代码示例

void showCustomBottomSheet(BuildContext context) {
  showModalBottomSheet(
    context: context,
    isDismissible: false, // 禁用默认关闭逻辑
    barrierColor: Colors.black54, // 保持原有的半透明屏障样式
    barrierTapCallback: () {
      // 判断键盘是否显示
      bool isKeyboardShow = MediaQuery.of(context).viewInsets.bottom > 0;
      
      if (isKeyboardShow) {
        // 关闭键盘,弹窗保留
        FocusManager.instance.primaryFocus?.unfocus();
      } else {
        // 关闭弹窗
        Navigator.pop(context);
      }
    },
    builder: (context) {
      // 适配键盘高度,避免输入框被遮挡
      return Padding(
        padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
        child: Container(
          height: 220,
          padding: const EdgeInsets.all(16),
          child: Column(
            children: [
              TextField(decoration: const InputDecoration(hintText: "输入内容测试键盘")),
              const SizedBox(height: 20),
              const Text("点击外部区域测试逻辑"),
            ],
          ),
        ),
      );
    },
  );
}

3. 细节说明

  • 弹窗内的输入框通过padding适配键盘高度,保证输入区域始终可见
  • 如果页面有多个可聚焦组件,primaryFocus会自动定位到当前激活的输入框,确保关闭对应键盘
  • 若遇到键盘动画过程中判断不准的情况,可以加个短延迟:
    Future.delayed(const Duration(milliseconds: 100), () {
      bool isKeyboardShow = MediaQuery.of(context).viewInsets.bottom > 0;
      // 后续逻辑不变
    });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 14:20:01