Flutter如何固定显示顶部状态栏同时底部启用immersiveSticky模式
解决方案
目前Flutter的SystemUiMode配置受原生系统限制,SystemUiMode.immersiveSticky确实不支持单独指定保留顶部状态栏,以下是可落地的两种实现方案:
方案1:自定义状态栏+全局immersiveSticky模式(推荐,双端兼容)
这是目前业内通用的稳定实现方案,完全可以满足保留顶部状态栏、底部无手势冲突的需求,实现步骤如下:
- 全局启用沉浸式粘性模式,解决底部手势遮挡问题
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); - 获取状态栏高度:可通过
MediaQuery.of(context).padding.top或者WidgetsBinding.instance.window.viewPadding.top获取,后者可以避免键盘弹出时高度计算异常 - 封装全局自定义状态栏Widget:高度设定为上述获取到的状态栏高度,可自行配置背景色、文字/图标样式,如需和系统临时调出的状态栏样式统一,可以配合
SystemChrome.setSystemUIOverlayStyle配置 - 页面结构适配:所有页面的Scaffold顶部预留对应状态栏高度的padding,或者直接将自定义状态栏设置为Scaffold的appBar,配置
toolbarHeight为状态栏高度即可
方案2:通过SystemUIChangeCallback强制保留顶部状态栏(仅Android可用,稳定性一般)
如果不想自定义状态栏,可通过系统UI变化回调强制顶部状态栏常驻,仅Android端生效:
SystemChrome.setSystemUIChangeCallback((systemOverlaysAreVisible) async { // 检测到系统UI隐藏时,强制恢复顶部状态栏显示 SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.top]); // 立即切回沉浸式粘性模式保证底部手势逻辑正常 SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); });
注意该方案在部分Android定制ROM上可能出现状态栏闪跳、回调不生效的问题,不建议生产环境使用。
适配注意事项
- iOS端:系统不允许单独控制底部导航栏的显隐策略,所有原生SystemUI配置均为全局生效,只有自定义状态栏方案可以实现需求
- Android端:开启全面屏手势时,建议自定义底部导航栏额外增加
MediaQuery.of(context).padding.bottom的底部内边距,避免系统手势提示线遮挡导航内容 - 自定义状态栏的样式完全可控,可适配不同页面的配色需求,灵活度远高于调整原生系统UI
内容的提问来源于stack exchange,提问作者DebuggingAsWell
相关产品推荐
相关产品推荐

