Flutter macOS端嵌套Navigator的Dialog如何通过ESC键关闭
问题根因
嵌套的Navigator默认会优先消费键盘回退事件(macOS下对应ESC键),用于弹出自身路由栈内的页面。只有当自身路由栈为空、无法继续弹出时,事件才会向上传递给负责控制弹窗关闭的上层导航器,因此会出现ESC无法关闭弹窗的问题。
可行解决方案
方案1:配置嵌套Navigator的onPopPage回调(推荐)
这是最贴合原生导航逻辑的方案,代码改动最小,同时完美适配序列式引导页的交互需求:内部有多级页面时按ESC先退回上一级内部页面,退到初始页后再按ESC就关闭整个弹窗。
import 'package:flutter/material.dart'; showDialog( context: context, builder: (context) => Dialog( child: SizedBox( width: 400, height: 400, child: Navigator( onGenerateRoute: (_) => MaterialPageRoute( builder: (_) => const Center(child: Text('hi there')) ), // 新增onPopPage配置即可 onPopPage: (route, result) { // 嵌套路由栈无页面可弹出时,返回false将pop事件向上传递 if (!route.didPop(result)) { return false; } // 正常弹出内部路由时消费事件 return true; }, ), ), ), );
方案2:手动监听ESC按键事件
如果需要更自定义的关闭控制逻辑,可以主动注册ESC按键监听:
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; showDialog( context: context, builder: (context) => Shortcuts( shortcuts: { LogicalKeySet(LogicalKeyboardKey.escape): VoidCallbackIntent(() { // 直接关闭弹窗 Navigator.of(context).pop(); }), }, child: Dialog( child: SizedBox( width: 400, height: 400, child: Navigator( onGenerateRoute: (_) => MaterialPageRoute( builder: (_) => const Center(child: Text('hi there')) ), ), ), ), ), );
内容的提问来源于stack exchange,提问作者Craig Edwards
相关产品推荐
相关产品推荐

