onpagescroll需配合custom导航栏才生效,pages.json中须为具体页面配置"navigationstyle": "custom";状态栏变色须调用uni.setnavigationbarcolor,且仅小程序平台有效,颜色值必须为十六进制。

onPageScroll 必须配合 custom 导航栏才生效
直接在页面里写 onPageScroll 却没反应?大概率是 pages.json 里没开自定义导航栏。微信/支付宝等小程序平台要求页面启用 "navigationStyle": "custom",onPageScroll 才会持续触发;H5 端还需确保根容器有明确高度和 overflow: scroll;App 端若用了 <scroll-view></scroll-view>,会拦截原生滚动,导致 onPageScroll 彻底失灵。
正确配置示例(pages.json):
{"path": "pages/index/index", "style": {"navigationStyle": "custom"}}
注意:这个字段必须写在具体页面的 style 下,不是全局 tabBar 或 navigationStyle 配置项里。
状态栏变色不能靠 CSS,得调 uni.setNavigationBarColor
自定义导航栏后,你看到的“状态栏”其实是页面顶部一块区域,但真机上系统状态栏(时间、信号格)的颜色仍由原生控制。想让它随滚动变化,必须调用 uni.setNavigationBarColor —— 它只在小程序平台(微信、支付宝、百度等)有效,H5 和 App 端不响应。
关键点:
-
frontColor和backgroundColor都是必填项,缺一个就无效 - 颜色值必须是十六进制格式,如
'#ffffff',不支持 rgba、hsl 或带 alpha 的值 - 不能在
onLoad里立刻调,建议放onReady或节流后的onPageScroll回调中 - 频繁调用会有延迟或丢帧,每秒别超过 10 次
滚动距离转颜色要自己算,没有自动映射
onPageScroll 只返回 { scrollTop: number },单位 px,从 0 开始递增。你想滚动 100px 后导航栏变成红色,就得手动做线性映射:
const opacity = Math.min(1, scrollTop / 100);<br>const bgColor = `rgb(${255 * (1 - opacity)}, ${255 * opacity}, 0)`;
然后把 bgColor 转成十六进制再传给 uni.setNavigationBarColor。别试图用 rgba() 直接塞进去——它不认。
常见坑:
- iOS 微信真机对调用频率敏感,连续快速滚动时可能卡住或跳变
- 安卓部分机型(如 MIUI)会强制跟随系统深色模式,覆盖 JS 设置
- 别在回调里直接
this.$forceUpdate()或反复setData,加个 16ms 节流就够了
App 和 H5 端根本没法用 setNavigationBarColor 改状态栏文字色
想让状态栏文字从黑变白?uni.setNavigationBarColor 的 frontColor 参数在 App 和 H5 上完全被忽略。App 端必须走原生 API:plus.navigator.setStatusBarStyle('light') 或 'dark',且只能在 onReady 后调,太早 plus 对象还没初始化。
H5 端更彻底:浏览器根本不暴露控制接口,所谓“变色”全是伪实现——比如用一个 fixed 的 <view></view> 盖在状态栏位置,再配 env(safe-area-inset-top) 做适配,但系统状态栏本身颜色纹丝不动。
所以跨端项目里,如果真需要状态栏文字动态切换,得条件编译分开处理:
#ifdef MP-WEIXIN<br>uni.setNavigationBarColor({ frontColor: '#ffffff', backgroundColor: '#000000' })<br>#endif<br>#ifdef APP-PLUS<br>plus.navigator.setStatusBarStyle('light')<br>#endif
最常被忽略的一点:iOS 原生层必须关闭全局状态栏控制,即 Info.plist 里 UIViewControllerBasedStatusBarAppearance 设为 YES,否则 JS 调用全失效。











