设为 custom 后原生胶囊被彻底移除,无法通过透明或 setNavigationBarColor 修改;需用 getMenuButtonBoundingClientRect 获取位置并自定义 view 模拟,注意适配状态栏、z-index、圆角、深色模式及点击逻辑。

导航栏设为 custom 后,胶囊按钮根本不存在了
你看到的“胶囊”是微信原生渲染的 UI 元素,只在 navigationStyle: "default" 时存在。一旦你在 pages.json 或页面级 style 中设为 "custom",微信会直接隐藏它——不是变透明,是彻底移除。所以“透明后改胶囊颜色”这个前提不成立,后续所有操作都基于一个已消失的对象,自然无效。
想让右上角看起来是白色胶囊,得自己画一个
核心思路是:用 uni.getMenuButtonBoundingClientRect() 拿到原生胶囊的位置,再用 <view> 模拟一个视觉一致的按钮。常见踩坑点:
- 没调用
uni.getMenuButtonBoundingClientRect()就硬写top: 44px—— iPhone 12/15 Pro 等机型状态栏高度不同,top值会错位 - 用
position: fixed但没加z-index: 999,被下拉刷新层或滚动内容盖住 - CSS 中写了
background-color: white,却漏了border-radius: 5px和padding,导致不像原生胶囊 - 没处理深色模式:白色背景在深色系统下可能看不清,建议用
color-scheme: light或监听wx.onThemeChange动态切 class
为什么 uni.setNavigationBarColor 对胶囊没用
uni.setNavigationBarColor 只影响原生导航栏区域(即 navigationStyle: "default" 下的标题栏背景),对胶囊按钮完全无控制权。微信从设计上就禁止修改胶囊样式,这是硬性限制,不是 API 调用时机或参数问题。你传 backgroundColor 再多次,胶囊该灰还是灰,该透还是透。
唯一能“改”的方式,就是放弃原生胶囊,走自定义路线。而这条路必须接受两个事实:
- 要手动适配各机型状态栏高度(
uni.getSystemInfoSync().statusBarHeight不可靠,优先用uni.getMenuButtonBoundingClientRect().top推算) - 要自己处理点击逻辑(比如跳转、弹窗),不能依赖原生胶囊的默认行为
真机调试时胶囊突然又出现了
大概率是页面配置没生效。检查三处:
-
pages.json里该页面的style是否明确写了"navigationStyle": "custom"(注意引号和大小写) - 是否在
App.vue或全局globalStyle里误设了"navigationStyle": "default",导致子页面继承 - 微信开发者工具缓存:删掉项目目录下的
unpackage文件夹,重新运行
最隐蔽的坑是:某些 UI 组件库(如 uView、uni-ui)的 <uni-nav-bar> 默认开启 fixed,且内部会自动读取原生胶囊位置。如果你同时用了它又手写了自定义胶囊,就会出现两个重叠的“胶囊”,真机上后者可能被遮挡,看起来像“时有时无”。



















