在 uni-app 项目中,如果运行到 App 端,Android 手机底部可能会出现系统虚拟按键栏,也就是返回、主页、多任务所在的那一块区域。这个区域不属于页面 DOM,也不是 uni-app 的 tabBar,所以不能通过普通 CSS 直接修改。
要修改它的背景色,需要调用 Android 原生能力。
一、适用范围
这个方案只适用于:
APP-PLUS + Android
不适用于:
css
H5
微信小程序
支付宝小程序
iOS
iOS 没有 Android 这种底部虚拟按键栏。如果想控制 iPhone 底部 Home Indicator 附近的颜色,需要设置页面背景或底部安全区容器背景。
二、核心方案
Android 原生设置底部虚拟导航栏颜色的方法是:
javascript
window.setNavigationBarColor(colorInt)
在 uni-app 里,可以通过 Native.js 调用:
arduino
const color = plus.android.newObject('android.graphics.Color')
const activity = plus.android.runtimeMainActivity()
const window = plus.android.invoke(activity, 'getWindow')
const colorInt = plus.android.invoke(color, 'parseColor', '#000000')
plus.android.invoke(window, 'setNavigationBarColor', colorInt)
三、推荐封装
可以抽成公共工具函数,例如:
typescript
// src/utils/navigationBar.ts
declare const plus: any
/** 设置安卓底部导航栏颜色 */
export const setAndroidNavigationBarColor = (colorValue = '#000000') => {
// #ifdef APP-PLUS
if (uni.getSystemInfoSync().platform !== 'android') return
try {
const Build = plus.android.importClass('android.os.Build')
if (Build.VERSION.SDK_INT < 21) return
const color = plus.android.newObject('android.graphics.Color')
const activity = plus.android.runtimeMainActivity()
const window = plus.android.invoke(activity, 'getWindow')
const colorInt = plus.android.invoke(color, 'parseColor', colorValue)
plus.android.invoke(window, 'setNavigationBarColor', colorInt)
} catch (error) {
console.warn('设置安卓底部导航栏颜色失败', error)
}
// #endif
}
四、页面中使用
比如登录页需要设置成黑色:
javascript
import { onShow } from '@dcloudio/uni-app'
import { setAndroidNavigationBarColor } from '@/utils/navigationBar'
onShow(() => {
setAndroidNavigationBarColor('#000000')
})
如果其他页面需要设置成白色:
scss
onShow(() => {
setAndroidNavigationBarColor('#ffffff')
})
建议放在 onShow,因为页面切换回来时可以重新设置,避免被其他页面覆盖。
五、为什么不用直接调用
下面这种写法可能会报错:
ini
const Color = plus.android.importClass('android.graphics.Color')
const main = plus.android.runtimeMainActivity()
const window = main.getWindow()
window.setNavigationBarColor(Color.parseColor('#000000'))
常见错误包括:
arduino
Cannot read property 'parseColor' of undefined
或:
vbnet
setNavigationBarColor is not a function
原因是 Native.js 里的 Java 对象代理不一定能像普通 JS 对象一样直接调用方法。更稳妥的方式是使用:
arduino
plus.android.invoke(...)
六、不要调用 setTabBarStyle
有些示例里可能会写:
arduino
plus.android.invoke(window, 'setTabBarStyle', colorInt)
这个不建议保留。
Android 原生 Window 没有 setTabBarStyle 这个方法,大概率无效,甚至可能报错。设置底部虚拟按键栏只需要:
setNavigationBarColor
七、iOS 怎么办
iOS 没有 Android 这种虚拟导航栏 API。iPhone 底部 Home Indicator 区域的颜色来自页面背景或底部容器背景。
可以通过 CSS 控制:
css
page {
background: #ffffff;
}
如果页面有底部固定按钮:
css
.footer {
padding-bottom: env(safe-area-inset-bottom);
background: #ffffff;
}
八、最终建议
如果项目只需要全局固定一个颜色,可以优先在 manifest 里配置 Android 的 navigationBarColor。
如果不同页面需要不同颜色,推荐使用本文的工具函数,在页面 onShow 中动态设置。
最终实践方案:
manifest 配默认色
页面 onShow 动态覆盖
iOS 通过页面背景和安全区背景处理
这样兼容性更好,也更方便维护。