navigationstyle: "custom"仅隐藏原生导航栏,不控制状态栏;需动态获取statusbarheight并结合css变量、env(safe-area-inset-top)及原生api(如plus.navigator)分端适配状态栏样式与高度。

uni-app里navigationStyle: "custom"不等于隐藏状态栏
很多开发者以为在pages.json中设了"navigationStyle": "custom"就万事大吉,结果在iOS真机上发现页面内容顶到了状态栏文字下面,安卓部分机型又黑底白字看不清。这是因为navigationStyle只控制原生导航栏的显隐,**不接管状态栏渲染逻辑**——尤其在App端,状态栏仍由系统原生控制。
- 小程序端:设
navigationStyle: "custom"后,状态栏区域完全暴露,需手动计算statusBarHeight并留白 - H5端:浏览器无状态栏概念,但顶部可能被地址栏遮挡,
titleNView配置无效,实际靠viewport或safe-area-inset-top处理 - App端(iOS/Android):状态栏颜色、图标明暗需单独调用
plus.navigator.setStatusBarStyle或setStatusBarBackground,且Android 4.4以下不支持前景色切换
statusBarHeight不能硬写20px或44px
全面屏机型状态栏高度差异极大:iPhone 8是20px,iPhone X是44px,iPhone 14 Pro灵动岛达54px。直接写死会导致刘海区内容被遮挡或底部留白过大。
- 必须通过
uni.getSystemInfo动态获取:e.statusBarHeight才是真实值 - 小程序还需额外获取胶囊按钮位置:
wx.getMenuButtonBoundingClientRect(),用于计算自定义导航栏总高(menuButtonInfo.bottom + menuButtonInfo.top - e.statusBarHeight) - App端可结合
plus.navigator.getStatusBarHeight(),比getSystemInfo更准(尤其在横屏或分屏场景)
三端统一适配状态栏的CSS方案
单纯靠JS获取高度还不够,得让样式层也响应式生效。推荐用CSS变量+安全区环境变量组合:
- 在
App.vue的onLaunch中注入变量:document.documentElement.style.setProperty('--status-bar-height', statusBarHeight + 'px') - 组件内用:
padding-top: var(--status-bar-height)或top: var(--status-bar-height) - 同时叠加
env(safe-area-inset-top)(iOS 11.2+、Android 10+支持),兜底处理异形屏:padding-top: max(var(--status-bar-height), env(safe-area-inset-top)) - 注意:H5端
env()无效,需靠媒体查询或UA判断降级为var(--status-bar-height)
App端状态栏文字颜色无法跨平台统一设置
navigationBarTextStyle只对小程序原生导航栏生效,App端必须走原生API。而iOS和Android对“文字颜色”的理解完全不同:
- iOS只认
"light"(白)/"dark"(黑),调用plus.navigator.setStatusBarStyle("light") - Android 6.0+才支持
setStatusBarStyle,且仅影响状态栏图标(电池、信号),文字颜色由setStatusBarBackground的背景色反推(深色背景自动亮色图标) - 最稳做法:App端统一用
plus.navigator.setStatusBarBackground("#ffffff")设背景,再配plus.navigator.setStatusBarStyle("dark")确保图标可见 - 切记:这些API仅在
APP-PLUS环境下可用,务必用<!-- #ifdef APP-PLUS -->包裹
状态栏适配真正的难点不在“怎么设”,而在“什么时候设”——页面跳转时系统可能重绘状态栏,onShow里重复调用setStatusBarStyle反而引发闪烁;iOS后台切前台时状态栏样式易丢失,需要监听plus.application.onResume事件补救。











