结论:不是导航栏“盖住”状态栏,而是 navigationstyle: "custom" 使页面容器 top 为 0 且未预留 --status-bar-height 空间,导致自定义内容与系统状态栏重叠;应添加高度为 var(--status-bar-height) 的占位 view,并注意 web-view 和 app 端 immersed 配置。

直接说结论:不是导航栏“盖住”了状态栏,而是你用了 navigationStyle: "custom" 却没给状态栏留出空间,导致自定义区域从屏幕顶部开始绘制,把状态栏内容(时间、信号、电池)压在了下面。
为什么 navigationStyle: "custom" 会导致遮挡
uni-app 的 navigationStyle: "custom" 会完全隐藏原生导航栏,但不会自动帮你避开状态栏 —— 它只是把页面容器的 top 设为 0。而 iOS/Android 的状态栏是系统级 UI,始终在最上层;你的自定义 view 如果没预留高度,就会和它视觉重叠。
常见错误现象:
- iPhone 上时间显示被导航栏背景色吞掉,只剩半截数字
- 安卓刘海屏下信号图标被裁掉上半部分
- 调试时用
inspect查看元素,发现第一个view的top: 0正好顶到屏幕最顶
用 --status-bar-height 做占位最稳妥
uni-app 在运行时会注入 CSS 变量 --status-bar-height,值随平台自动变化:小程序固定 25px,App 端取 sysinfo.statusBarHeight,H5 通常为 0。这是官方推荐的适配方式,无需手动调 uni.getSystemInfo。
实操建议:
- 在自定义导航栏页面的最顶部加一个空
view,样式设为height: var(--status-bar-height); width: 100% - 这个
view不需要内容,纯占位,不设背景色也不会影响交互 - 确保它在 DOM 顺序上位于导航栏容器之前,否则 margin/padding 容易错乱
- 不要用
padding-top替代,因为 padding 会撑开父容器,可能影响 fixed 定位或滚动行为
WebView 场景下必须手动调整 webview 位置
如果你在页面里用了 <web-view></web-view> 组件,它默认全屏渲染,会直接覆盖状态栏 —— 这时 CSS 变量无效,必须通过原生 API 调整其布局。
关键点:
-
this.$scope.$getAppWebview()获取当前页面 webview 实例 - 必须等页面 ready 后再操作,建议用
setTimeout(..., 200)或监听onReady - 调用
wv.setStyle({ top: statusBarHeight, height: windowHeight - statusBarHeight }) -
statusBarHeight一定要从uni.getSystemInfo的 success 回调里取,不能写死
App 端额外注意 immersed 配置
即使做了 CSS 占位,App 打包后仍可能顶部多出一块空白 —— 这通常是 manifest.json 里 app-plus.statusbar.immersed 配置冲突导致的。
检查并确认:
- manifest.json 中
"immersed": false(推荐),避免系统强制沉浸式 - 如果设为
true,则需配合plus.navigator.setFullscreen(true),但会失去状态栏文字,一般不建议 - 不要同时在
pages.json和manifest.json里对状态栏做相反配置,容易互相覆盖
最容易被忽略的是:iOS 真机上胶囊按钮(右上角返回/分享等)的高度 ≠ 状态栏高度,它额外有 8px 左右的上下间距。如果你的自定义导航栏要对齐胶囊按钮,光靠 --status-bar-height 不够,得额外加逻辑读取 capsule 位置 —— 但绝大多数场景,只处理状态栏就够了。











