uni-app 动态控制原生导航栏显隐需分平台处理:小程序/H5 可通过 pages.json 预设 navigationBarHidden 并配合 onShow/onHide 模拟切换,APP 端仅支持通过 navigationStyle: "custom" 配置页面级隐藏且无法运行时更改。

uni-app 动态控制原生导航栏显隐必须分平台处理
直接写 navigationBarHidden: true 或调用 uni.hideNavigationBar() 在多数场景下无效——uni-app 没有提供跨端动态切换原生导航栏的统一 API。所谓“动态”,实际是靠页面级配置 + 生命周期钩子 + 平台特有逻辑组合实现,且 APP 端根本无法运行时切换原生导航栏状态。
小程序/H5 端:用 navigationBarHidden + onShow/onHide 控制最可靠
这两个平台支持运行时修改 navigationBarHidden 配置,但仅限在页面级 style 中声明,不能通过 JS 动态写入 pages.json。真正能“动态”的做法是:提前在 pages.json 中为该页面设置可变配置,并配合生命周期触发重载或样式切换。
- 在 pages.json 对应页面的
style里写"navigationBarHidden": false(默认显示),不要设为true—— 否则后续无法“显示”回来 - 需要隐藏时,在
onShow中调用uni.setNavigationBarColor({ frontColor: '#000000', backgroundColor: '#ffffff' })配合透明背景模拟隐藏效果(仅 H5 有效) - 微信小程序不支持运行时隐藏,只能跳转到一个已配
navigationBarHidden: true的新页面;若需“切页不刷新”,本质是用自定义导航栏覆盖,原生栏仍存在 - 别在
mounted或onLoad调用uni.hideNavigationBar()—— 这个 API 不存在,官方从未提供
APP 端:navigationStyle: "custom" 是唯一入口,无法中途切换
APP 端的原生导航栏由 WebView 容器控制,navigationBarHidden 字段完全被忽略。所谓“动态”,其实是预设两套页面配置,再用路由跳转切换:
- 想显示原生导航栏的页面,pages.json 中必须设
"navigationStyle": "default"(且不能与"titleNView": false共存) - 想隐藏的页面,必须设
"navigationStyle": "custom"+"titleNView": false,二者缺一不可 - 不能在同一个页面内通过 JS 切换
navigationStyle值——这是编译期配置,运行时修改不生效 - 如果真要“看起来动态”,只能用
uni.navigateTo跳到另一个已配置好custom的页面,再用uni.navigateBack回来,视觉上形成切换感
隐藏后内容被顶出/遮挡?重点检查 status bar 和 titleNView 行为
很多“隐藏失败”其实是内容布局错位导致的假象。APP 端启用 navigationStyle: "custom" 后,系统状态栏依然存在,而页面容器默认未适配,容易造成顶部 20px 内容被遮挡或底部留白。
- 务必在
onShow(不是mounted)中加#ifdef APP-PLUS判断,调用plus.navigator.setFullscreen(true)收起状态栏 -
titleNView: false必须显式声明,否则某些 Android 机型(如 HyperOS)会渲染一个空 title 区域,产生 1px 白边 - 自定义导航栏高度建议设为
44px(iOS)或48px(Android),并用env(safe-area-inset-top)适配刘海屏,否则滚动时可能突然露底 - 别用
margin-top: -44px强行上拉——这会导致下拉刷新区域偏移、返回手势失效等连锁问题
真正的动态控制只存在于“页面维度”,而非“运行时状态”。把导航栏当成页面属性来设计,而不是 DOM 元素来操作,才能避开绝大多数兼容性陷阱。


















