uni.getmenubuttonboundingclientrect() 返回胶囊按钮的边界信息对象,包含 top、bottom、left、right、width、height 属性,单位 px,原点为屏幕左上角。

uni.getMenuButtonBoundingClientRect() 返回什么
这个 API 是唯一可靠来源,返回对象如 {top: 24, bottom: 56, left: 230, right: 317, width: 87, height: 32}。所有坐标都以屏幕左上角为原点(0,0),单位是 px。height 就是胶囊按钮自身高度,但它不能直接当“导航栏高度”用——因为导航栏要包含状态栏 + 上下留白 + 胶囊本身。
为什么不能直接用 height 当标题栏高度
常见错误是只取 menuButtonInfo.height(比如 32px)作为自定义导航栏高度,结果发现内容被裁切或顶部留白过大。原因在于:胶囊按钮上下有动态留白,且留白不相等(尤其在 iPhone 14 Pro、部分安卓机型上)。top 是胶囊上边距屏幕顶部的距离,statusBarHeight 是状态栏高度(如 44px),二者差值才是胶囊上边距状态栏底边的距离,而这个距离 ≠ 胶囊下边距。
- 错误写法:
titleBarHeight = menuButtonInfo.height - 错误写法:
titleBarHeight = menuButtonInfo.height + (menuButtonInfo.top - statusBarHeight) * 2(假设上下留白对称,但实际不成立) - 正确逻辑:导航栏总高度应覆盖从状态栏顶(y=0)到胶囊底(y=
menuButtonInfo.bottom)的整个垂直跨度,再补上胶囊下方等量留白?不,微信没公开这个“下方留白”,所以必须用更稳的公式
真正该用的公式是 menuButtonInfo.bottom + menuButtonInfo.top - statusBarHeight
这是经过多机型实测验证的可靠公式,它等价于:从屏幕顶部到胶囊底部的距离 + 从屏幕顶部到胶囊顶部的距离 − 状态栏高度。几何上刚好等于“状态栏高度 + 胶囊上方空隙 + 胶囊自身高度 + 胶囊下方空隙”。它不依赖上下留白是否对称,也不需要猜测“下方留白”是多少。
- 调用时机必须在
onLoad或onReady钩子中,避免 SSR 或生命周期过早导致uni.getMenuButtonBoundingClientRect()返回null - 务必搭配
uni.getSystemInfoSync().statusBarHeight使用,不能硬编码 44 或 20 - 需做兜底:如果 API 不可用(如非微信小程序环境),返回默认值如 44 或 88
- 注意:该高度是 px 单位,CSS 中若用 rpx,需自行转换(
uni.upx2px())
容易被忽略的兼容性坑
很多开发者在真机调试时才发现问题:模拟器里 uni.getMenuButtonBoundingClientRect() 正常返回,但某些安卓微信版本(如 8.0.49)或 iOS 微信分屏模式下会返回空对象或 width/height 为 0。这时候直接解构会报错。
- 必须加判空:
const res = uni.getMenuButtonBoundingClientRect(); if (!res || res.width - 不要在
data顶层直接赋值,应在生命周期内异步获取并响应式更新 - 在
pages.json中确认对应页面已设置"navigationStyle": "custom",否则胶囊按钮行为异常 - 抖音小程序、QQ 小程序等平台无此 API,跨平台项目需用条件编译包裹(
#ifdef MP-WEIXIN)
实际开发中,最易出错的不是公式本身,而是把“胶囊高度”和“导航栏高度”混为一谈,以及忽略 API 在低版本微信中的不可靠性。










