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

Flutter GoRouter:按下返回键关闭ModalBottomSheet的解决方法

解决GoRouter+底部导航栏下ModalBottomSheet返回键不关闭问题

问题原因

你当前用useRootNavigator: true将弹窗挂载在根导航器上,但打开弹窗时传入的是分支导航器(OtherDetailPage所在分支)的context。按下返回键时,GoRouter优先处理分支导航器的路由栈回退,而非根导航器上的弹窗关闭逻辑。

解决方案

方案1:使用根导航器的Context打开弹窗

直接用全局根导航器key获取context来打开弹窗,让弹窗生命周期与根导航器绑定,返回键会优先触发弹窗关闭。

修改弹窗打开代码:

showModalBottomSheet(
  isScrollControlled: true,
  useRootNavigator: true,
  context: rootNavKey.currentContext!, // 替换为根导航器的context
  enableDrag: false,
  builder: (context) {
    return MyModalContent();
  },
);

注意:确保rootNavKey是全局初始化的,且已在GoRouter初始化时传入navigatorKey: rootNavKey。

方案2:用WillPopScope拦截弹窗内的返回事件

在弹窗内容外层包裹WillPopScope,手动拦截返回键事件,关闭弹窗并阻止路由回退。

修改弹窗代码:

showModalBottomSheet(
  isScrollControlled: true,
  useRootNavigator: true,
  context: context,
  enableDrag: false,
  builder: (context) {
    return WillPopScope(
      onWillPop: () async {
        Navigator.of(context).pop(); // 关闭弹窗
        return false; // 阻止系统默认的路由回退行为
      },
      child: MyModalContent(),
    );
  },
);

方案3:自定义GoRouter全局返回拦截逻辑

如果需要全局统一处理这类场景,可以在GoRouter初始化时配置onPopPage,优先关闭根导航器上的弹窗再处理路由:

static final router = GoRouter(
  initialLocation: homePath,
  navigatorKey: rootNavKey,
  onPopPage: (route, result) {
    // 检查根导航器是否有可关闭的弹窗路由
    if (rootNavKey.currentState != null && rootNavKey.currentState!.canPop()) {
      rootNavKey.currentState!.pop();
      return false; // 不执行默认的路由回退
    }
    return route.didPop(result);
  },
  routes: [
    // 你的路由配置...
  ],
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 13:12:12