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

Flutter中如何使用GoRouter.of(context).backButtonDispatcher.forget属性

Web端弹窗禁用返回按钮实现思路

核心逻辑

利用BackButtonDispatcher的回调拦截机制:弹窗显示时注册一个返回拦截回调(返回true表示阻止默认返回行为),弹窗关闭时移除该回调,恢复正常导航。

具体实现步骤

1. 管理回调实例

在弹窗相关的状态类中,定义变量保存回调入口:

BackButtonCallbackEntry? _backButtonEntry;

2. Dialog/BottomSheet场景实现

当打开弹窗时立即注册拦截,弹窗关闭后移除:

void showCustomDialog() async {
  // 注册拦截回调,返回true阻止浏览器返回
  _backButtonEntry = Navigator.of(context).backButtonDispatcher?.addCallback(() async {
    return true;
  });

  // 打开弹窗
  await showDialog(
    context: context,
    barrierDismissible: true,
    builder: (_) => AlertDialog(
      title: const Text("弹窗"),
      content: const Text("当前禁用浏览器返回按钮"),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: const Text("关闭"),
        ),
      ],
    ),
  );

  // 弹窗关闭后移除拦截
  _backButtonEntry?.forget();
  _backButtonEntry = null;
}

3. 自定义全屏弹窗页面场景

如果是通过Navigator.push打开的全屏弹窗,在页面生命周期中处理拦截:

class PopupPage extends StatefulWidget {
  const PopupPage({super.key});

  @override
  State<PopupPage> createState() => _PopupPageState();
}

class _PopupPageState extends State<PopupPage> {
  BackButtonCallbackEntry? _backButtonEntry;

  @override
  void initState() {
    super.initState();
    // 页面初始化时注册拦截
    _backButtonEntry = Navigator.of(context).backButtonDispatcher?.addCallback(() async {
      return true;
    });
  }

  @override
  void dispose() {
    // 页面销毁时移除拦截
    _backButtonEntry?.forget();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("全屏弹窗")),
      body: Center(
        child: TextButton(
          onPressed: () => Navigator.pop(context),
          child: const Text("关闭页面"),
        ),
      ),
    );
  }
}

4. 进阶:带确认的拦截逻辑

如果需要用户确认后才允许返回,可在回调中嵌套确认弹窗:

_backButtonEntry = Navigator.of(context).backButtonDispatcher?.addCallback(() async {
  final confirmExit = await showDialog<bool>(
    context: context,
    builder: (_) => AlertDialog(
      title: const Text("确认离开?"),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context, false),
          child: const Text("取消"),
        ),
        TextButton(
          onPressed: () => Navigator.pop(context, true),
          child: const Text("确认"),
        ),
      ],
    ),
  );
  // 返回false允许返回,true继续拦截
  return !(confirmExit ?? false);
});

注意事项

  • 确保所有弹窗关闭路径都调用forget(),包括点击弹窗外部(barrierDismissible: true)、代码调用Navigator.pop等场景。
  • 如果Navigator.of(context).backButtonDispatcher为null,可尝试使用WidgetsBinding.instance.defaultBackButtonDispatcher替代。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 14:00:16