You need to enable JavaScript to run this app. Flutter macOS端嵌套Navigator的Dialog如何通过ESC键关闭
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 14:45:01