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

Flutter升级后WillPopScope/PopScope在Android返回键无响应(go_router场景)

解决GoRouter + StatefulShellBranch下PopScope/WillPopScope无响应的问题

核心原因

GoRouter的StatefulShellBranch会接管页面的路由栈管理,直接在Dashboard的Scaffold外层套PopScope/WillPopScope,会被GoRouter的路由拦截逻辑覆盖,导致回调无法触发。

具体解决步骤

1. 正确放置PopScope的位置

需要将PopScope放在StatefulShellRoute的builder内部,而非Dashboard页面的外层。StatefulShellRoute作为底部导航的路由容器,只有在这里设置才能让GoRouter正确传递返回键事件。

示例代码:

StatefulShellRoute.indexedStack(
  builder: (context, state, navigationShell) {
    // 在此处包裹PopScope
    return PopScope(
      canPop: false, // 阻止默认返回行为
      onPopInvoked: (bool didPop) async {
        if (!didPop) {
          // 实现双击返回退出逻辑
          DateTime currentTime = DateTime.now();
          static DateTime? _lastPressedTime;
          if (_lastPressedTime == null || currentTime.difference(_lastPressedTime!) > const Duration(seconds: 2)) {
            _lastPressedTime = currentTime;
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('再按一次退出应用')),
            );
          } else {
            SystemNavigator.pop(); // 退出应用
          }
        }
      },
      child: DashboardPage(navigationShell: navigationShell),
    );
  },
  branches: [
    StatefulShellBranch(
      routes: [
        GoRoute(
          path: '/home',
          builder: (context, state) => const HomePage(),
        ),
      ],
    ),
    // 其他底部导航分支...
  ],
)

2. 兼容子页面路由栈(可选)

如果子页面存在嵌套路由(比如Home页打开了详情页),需要在回调中先判断子页面路由栈是否可返回,再处理双击退出逻辑:

onPopInvoked: (bool didPop) async {
  if (!didPop) {
    final router = GoRouter.of(context);
    // 子页面路由栈有内容时,优先返回子页面
    if (router.canPop()) {
      router.pop();
    } else {
      // 触发双击退出逻辑
      DateTime currentTime = DateTime.now();
      static DateTime? _lastPressedTime;
      if (_lastPressedTime == null || currentTime.difference(_lastPressedTime!) > const Duration(seconds: 2)) {
        _lastPressedTime = currentTime;
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('再按一次退出应用')),
        );
      } else {
        SystemNavigator.pop();
      }
    }
  }
}

3. 关键注意点

  • 必须设置canPop: false,避免GoRouter执行默认返回行为,确保回调逻辑生效。
  • 不要在Dashboard页面内部嵌套PopScope/WillPopScope,否则会被外层路由容器拦截。
  • 测试时需确保当前处于底部导航的根页面(无子页面栈),否则返回键会优先处理子页面路由。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 09:12:14