导航栏不支持点击穿透,所谓“穿透”是误用 custom 模式导致底层内容暴露引发的交互错觉;正确做法是:该用原生栏时勿设 navigationStyle: "custom",该自定义时须完整接管布局与事件逻辑。

导航栏本身不支持点击穿透——所谓“穿透”,其实是误用了 custom 模式后,底层内容暴露在原生导航栏区域导致的交互错觉。 真正要解决的不是“让导航栏透点过去”,而是:该显示原生栏时别手抖设 navigationStyle: "custom",该自定义时别忘了接管所有交互逻辑。
navigationStyle: "custom" 后为啥像“穿透”了
设成 navigationStyle: "custom" 并不会让导航栏变透明或可穿透,它只是关掉原生导航栏、把控制权交给你。此时你写的 <view class="nav"> 是普通 webview 层级的 DOM,系统状态栏仍盖在最上层——如果没手动加 padding-top: var(--status-bar-height),你的内容就会被状态栏裁掉;如果又没设 background-color: transparent,看起来就像“原生栏还在”。用户点到空处,实际是点到了你没覆盖到的区域,或者点穿了遮罩层(比如弹窗没拦住事件)。
- 常见错误现象:页面顶部空白、标题文字被切掉、点导航栏区域却触发了下方按钮
- 这不是穿透,是布局错位 + 事件未拦截的组合问题
- 微信小程序里
navigationStyle: "custom"根本不支持状态栏适配,--status-bar-height值为 0,强行用会出白边或错位
真需要“穿透式”交互?优先用原生导航栏
如果你的目标是点击导航栏某区域(比如 logo)跳转,或让搜索框直接响应输入,就别用 navigationStyle: "custom"。直接用原生导航栏 + uni.setNavigationBarColor 和 uni.setNavigationBarTitle 控制样式和文字,再在页面内放一个绝对定位的 <view> 覆盖在导航栏对应位置,绑定 @tap 即可。这样既稳定,又不用处理状态栏高度、下拉刷新冲突、软键盘顶起等问题。
- 原生导航栏下,
uni.getSystemInfo().statusBarHeight在 App 端可用,但 H5 和小程序仍不可靠,建议只在 App 端启用该方案 - 覆盖层
<view>必须加z-index: 999(高于原生栏默认层级),且宽高需精确匹配目标热区 - 避免用
pointer-events: none做“透明穿透”,iOS Safari 对该属性支持极差,尤其在有transform的父容器下会完全失效
非要用 custom 导航栏并允许点击穿透?得自己拦事件
如果业务强依赖自定义导航栏(比如带复杂动画、左右滑动 tab),又希望某个区域“透过去”,唯一可行路径是:在该区域 DOM 上显式绑定 @tap.stop.prevent 或手动调 e.stopPropagation(),然后在回调里判断坐标或元素,决定是否转发给下层。但这本质是模拟,不是真穿透。
- 不要写
@click="handleTap",改用@tap.stop="handleTap",确保 iOS 下能捕获 touch 事件 - 若需转发,用
document.elementFromPoint(x, y)获取真实目标元素,再手动触发其click事件(注意兼容性) - 禁用滚动穿透比点击穿透更关键:在导航栏容器外层加
@touchmove.stop.prevent,否则手指一滑,整个页面跟着动 - 真机调试必须用正式打包的 IPA/APK,HBuilderX 模拟器不注入
--status-bar-height,也测不出原生层叠加效果
最易被忽略的一点:custom 导航栏一旦启用,uni.setNavigationBarColor 和 uni.setNavigationBarTitle 就彻底失效——它们只作用于原生栏。你看到颜色没变、标题没更新,不是 API 调用失败,而是根本没地方画。


















