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

Flutter基于auto_route嵌套导航时,模态底部弹窗打开后状态栏未变暗的问题求助

Flutter基于auto_route嵌套导航时,模态底部弹窗打开后状态栏未变暗的问题求助

我之前用auto_route做嵌套导航时,也碰到过一模一样的问题——非嵌套导航下打开showModalBottomSheet,状态栏会自动变暗,但切换到嵌套导航后这个效果就没了。折腾了好一阵才搞明白原因,给你分享下解决思路和办法:

问题根源

在嵌套导航结构里,你调用showModalBottomSheet时传入的context大概率是嵌套导航器的context,而非根导航器的context。Flutter的状态栏全局UI效果(比如变暗遮罩)是由根导航器层级负责管理的,嵌套导航器的context属于子层级,系统没办法识别要对全局状态栏应用效果,所以就出现了状态栏保持原色的情况。

解决办法(按推荐优先级排序)

1. 使用根导航器的Context调用Bottom Sheet

这是最直接也最符合Flutter设计的方案——获取根导航器的context,用它来启动showModalBottomSheet,让系统正确识别要应用全局状态栏效果。

修改你的代码只需要两步:

  • 在调用showModalBottomSheet前,获取根导航器的context
  • 把原来的context参数替换成根context

修改后的完整代码:

void showCustomBottomSheet(BuildContext context) {
  // 获取根导航器的Context
  final rootContext = Navigator.of(context, rootNavigator: true).context;

  showModalBottomSheet(
    context: rootContext, // 替换为根Context
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
    ),
    backgroundColor: Colors.white,
    isScrollControlled: true,
    builder: (context) {
      return Padding(
        padding: EdgeInsets.only(
          bottom: MediaQuery.of(context).viewInsets.bottom,
          top: 16,
          left: 16,
          right: 16,
        ),
        child: Wrap(
          children: [
            Center(
              child: Container(
                width: 40,
                height: 4,
                decoration: BoxDecoration(
                  color: Colors.grey[300],
                  borderRadius: BorderRadius.circular(2),
                ),
              ),
            ),
            SizedBox(height: 16),
            Text(
              'Bir seçenek seç',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            ListTile(
              leading: Icon(Icons.share),
              title: Text('Paylaş'),
              onTap: () {
                Navigator.pop(context, 'paylas');
              },
            ),
            ListTile(
              leading: Icon(Icons.link),
              title: Text('Link kopyala'),
              onTap: () {
                Navigator.pop(context, 'link');
              },
            ),
            ListTile(
              leading: Icon(Icons.delete),
              title: Text('Sil'),
              onTap: () {
                Navigator.pop(context, 'sil');
              },
            ),
          ],
        ),
      );
    },
  ).then((value) {
    if (value != null) {
      print("Seçilen: $value");
    }
  });
}

如果上面的方法获取根context失败(比如某些复杂嵌套场景),可以用全局Key绑定根导航器:

  • 先在全局定义根导航Key:
    final GlobalKey<NavigatorState> rootNavigatorKey = GlobalKey<NavigatorState>();
    
  • 在MaterialApp.router中绑定这个Key:
    MaterialApp.router(
      routerDelegate: AutoRouterDelegate(
        _appRouter,
        navigatorKey: rootNavigatorKey, // 绑定根导航Key
      ),
      routeInformationParser: _appRouter.defaultRouteParser(),
    )
    
  • 最后在Bottom Sheet中使用这个Key的context:
    showModalBottomSheet(
      context: rootNavigatorKey.currentContext!,
      // 其他参数不变
    )
    

2. 手动控制状态栏样式(备选方案)

如果根context的方法不生效,还可以手动控制状态栏的颜色,在打开Bottom Sheet时设置为你需要的变暗效果,关闭时恢复原样式:

import 'package:flutter/services.dart'; // 记得导入这个包

void showCustomBottomSheet(BuildContext context) {
  // 保存当前状态栏样式,用于后续恢复
  final originalStatusStyle = SystemChrome.latestStyle;

  // 打开Bottom Sheet时,设置状态栏为变暗效果
  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
    statusBarColor: Colors.deepPurple.withOpacity(0.7), // 替换成你需要的变暗颜色
    statusBarIconBrightness: Brightness.light, // 如果状态栏图标需要变亮,就加这个
  ));

  showModalBottomSheet(
    // 原有的参数不变
  ).then((value) {
    // 关闭Bottom Sheet后,恢复原来的状态栏样式
    if (originalStatusStyle != null) {
      SystemChrome.setSystemUIOverlayStyle(originalStatusStyle);
    }
    if (value != null) {
      print("Seçilen: $value");
    }
  });
}

这个方案要注意:如果同时打开多个弹窗,需要小心样式覆盖的问题,所以优先推荐第一种方案。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 13:33:11