Flutter中WillPopScope的onWillPop监听设备返回键失效问题
问题解决:Flutter中WillPopScope设备返回键不触发的问题
问题原因
你在TeamSetup和ManagePreference页面中重复创建了MaterialApp,这会导致每个页面都拥有独立的导航栈(Navigator)。当按下设备返回键时,系统会直接退出当前页面的MaterialApp实例,而非执行页面内WillPopScope的onWillPop逻辑,所以两次返回直接回到了根页面HomeScreen。而AppBar的返回按钮使用的是当前页面上下文的Navigator.pop(),所以能正常工作。
修复方案
只在根页面HomeScreen中保留MaterialApp,其他页面仅返回Scaffold(或包裹WillPopScope的Scaffold),确保所有页面共享同一个导航栈。
修改后的代码示例
TeamSetup页面修改
class _TeamSetupState extends State<TeamSetup> { @override Widget build(BuildContext context) { // 移除外层的MaterialApp return WillPopScope( onWillPop: onBackPress, child: Scaffold( appBar: customAppBar(context, screenHeight, "标题", "子标题"), // 传入对应参数 body: SafeArea( // 原有页面内容 child:PopupMenuButton( onSelected: (value) { Navigator.push(context,MaterialPageRoute( builder: (context) => ManagePreference(user: widget.user, team: teamList[index]), )); }, ), ), ), ); } Future<bool> onBackPress() { Navigator.pop(context); return Future.value(false); } }
ManagePreference页面修改
class _ManagePreferenceState extends State<ManagePreference> { @override Widget build(BuildContext context) { // 移除外层的MaterialApp return WillPopScope( onWillPop: _onWillPop, child: Scaffold( appBar: customAppBar(context, screenHeight, "标题", "子标题"), // 传入对应参数 body: SafeArea( // 原有页面内容 ), ), ); } Future<bool> _onWillPop() async { return (await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('确定要退出吗?'), content: const Text('你确定要退出应用吗?'), actions: <Widget>[ ElevatedButton( onPressed: () => Navigator.of(context).pop(false), child: const Text('取消'), ), ElevatedButton( onPressed: () => Navigator.of(context).pop(true), child: const Text('确定'), ), ], ), )) ?? false; } }
HomeScreen页面保持不变
确保HomeScreen是唯一包含MaterialApp的页面,所有后续页面通过Navigator.push推入同一个导航栈。
额外说明
如果需要全局主题、路由配置等,应该在根MaterialApp中统一设置,避免在每个页面重复创建MaterialApp,否则会导致导航栈混乱、主题不统一等问题。
内容的提问来源于stack exchange,提问作者KJEjava48
相关产品推荐
相关产品推荐

