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
相关产品推荐
相关产品推荐

