uni-app适配暗黑模式/夜间模式/深色模式/暗黑主题(DarkMode)
uni-app适配暗黑模式/夜间模式/深色模式/暗黑主题(DarkMode)
此文档仅描述5+ App项目如何适配暗黑模式,uni-app项目请参考:https://uniapp.dcloud.net.cn/tutorial/darkmode.html#open-darkmode
iOS13开始引入了暗黑模式(DarkMode),Android10 引入暗黑模式,在暗黑模式下,系统界面配色都会相应变暗,同时App也需要进行适配。
特别说明
iOS平台
苹果近日对App Store商店的审核指南做了一次更新并发了一份公告,要求所有的APP 在4月30号前使用iOS 13 SDK开发应用,很多开发者错误理解成使用iOS 13 SDK开发应用就必须适配暗黑模式,实际上苹果的官方开发者文档从未强制要求应用必须适配深色样式(暗黑模式),完整解读参考:https://ask.dcloud.net.cn/article/37037。
重点:不适配暗黑模式,一样可以正常上Appstore。但是适配了暗黑模式,没适配利索,页面有黑有白,就可能会被拒绝上架。
注意:必须iOS13+设备上才支持
Android平台
注意:必须Android10+设备上才支持
开启适配暗黑模式(DarkMode)
为了保证应用的兼容性,HBuilderX打包生成的App默认已关闭兼容暗黑模式,需按以下方法配置开启适配暗黑模式。
开启适配暗黑模式后,弹出系统授权框将按当前系统设置的外观样式显示(可在 “设置” -> “显示与亮度” -> “外观” 中更改),应用中的页面则需要开发者根据下面的API获取当前系统外观模式进行适配处理。
注意:如果未开启适配黑暗模式,将无法获取当前系统的外观样式
打开项目的manifest.json文件,切换到“源码视图”项
iOS平台
在 “plus” -> “distribute” -> “apple” 节点下添加 defaultTheme 节点
"plus": {
"distribute": {
"apple": {
"UIUserInterfaceStyle": "Automatic", //不推荐使用,设置light或dark后将无法跟随系统
"defaultTheme": "light" | "dark" | "auto" //HBuilderX 3.6.10及以上版本支持
//...
},
//...
},
//...
Android平台
在 “plus” -> “distribute” -> “google” 节点下添加 defaultNightMode 节点
"plus": {
"distribute": {
"google": {
"defaultNightMode": "light" | "dark" | "auto"
//...
},
//...
},
//...
保存后,提交云端打包后生效
暗黑模式适配主要包括启动界面,应用中的页面,另一部分是特定功能弹出系统原生界面(如alert提示框)和iOS平台安全区域外背景颜色,下面会详细说明分别如何适配。
启动页
官方提供的默认启动页已适配 ‘暗黑模式’,会自动跟随系统模式改变背景颜色;自定义启动页请参考文档 自定义启动页
iOS安全区域适配
开启安全区域占位
在 manifest.json文件的"plus" 节点下添加 “safearea” 适配iOS的安全区域,“background” 对应正常模式下安全区域外的背景颜色,"backgroundDark"对应暗黑模式下安全区域外的背景颜色
"plus" : {
"safearea": { //iOS平台的安全区域
"background": "#ffffff",
"backgroundDark": "#2f0508", // HX 3.1.19+支持
"bottom": {
"offset": "auto"
}
}
...
关闭安全区域占位
将 “offset” 置为 “none” 关闭安全区域的占位,注:关闭安全区域占位在刘海屏页面内容可能会被 “homeBar” 挡住,需要自行适配,具体请参考文档 iOS刘海屏适配
"safearea": {
"bottom": {
"offset": "none"
}
}
更多关于 “safearea” 的说明请参考 manifest.json 说明
应用中页面适配暗黑模式
在应用中需要获取当前系统设置的外观模式格是否为暗黑模式,如果是则需要调整应用整体UI风格样式进行适配。
html页面可通过CSS适配
推荐使用CSS中的媒体查询 prefers-color-scheme 进行适配
@media (prefers-color-scheme: dark){
.content {
background-color: #1B1C1E;
color: white;
}
}
注意:如果未开启适配黑暗模式,以上媒体查询样式将不会生效
获取当前系统外观模式
对于页面中的原生标题栏(TitleNView),则需获取当前的外观模式,动态修改样式进行适配。
5+ API:plus.navigator.getUIStyle获取当前系统外观模式。
返回"dark"表示当前为深色样式(DarkMode),即暗黑模式;"light"表示当前为浅色样式(LightMode),即普通模式。
function getUIStyle(){
var style = plus.navigator.getUIStyle();
if('dark'==style){
console.log('当前为暗黑模式');
}else{
console.log('当前为普通模式');
}
}
监听系统外观模式改变
应用启动后,用户有可能改变系统外观,这时候可以通过监听切换暗黑模式事件进行处理。
5+ App(WAP2APP)项目,可在在页面中监听"uistylechange"事件
document.addEventListener('uistylechange', function(){
var style = plus.navigator.getUIStyle();
console.log(('dark'==plus.navigator.getUIStyle())?'切换为暗黑模式':'切换为普通模式');
}, false);
系统原生界面适配暗黑模式
应用开启适配暗黑模式后,系统原生界面(plus.nativeUI)默认会自动适配系统设置的外观样式。
如果系统当前设置为深色外观(暗黑模式),则plus.nativeUI弹出的所有界面自动显示为深色(暗黑模式)样式;如果系统当前设置为浅色外观,则plus.nativeUI弹出的所有界面显示为浅色样式。
如系统提示框(plus.nativeUI.alert)
如果不想自动适配系统设置的外观样式,可以调用plus.nativeUI.setUIStyle强制设置原生界面的外观样式。
以下示例强制应用弹出原生界面为深色(暗黑模式)外观样式,即使系统没有设置为深色外观(暗黑模式):
plus.nativeUI.setUIStyle('dark'); // ‘light’表示浅色外观样式
即使应用没有开启适配暗黑模式,此API也可生效
受影响的5+ API弹出系统原生界面
- plus.nativeUI.actionSheet
- plus.nativeUI.alert
- plus.nativeUI.confirm
- plus.nativeUI.previewImage
- plus.nativeUI.showWaiting
- plus.nativeUI.pickDate
- plus.nativeUI.pickTime
- plus.nativeUI.prompt
- plus.nativeUI.toast
受影响的uni-app弹出系统原生界面
- uni.showToast
- uni.showLoading
- uni.showModal
- uni.showActionSheet
- uni.previewImage
- picker(仅时间选择器,即:mode = time)
在处理uni-app适配暗黑模式(DarkMode)时,可以通过CSS变量和JavaScript逻辑来动态切换主题。以下是一个基本的实现示例,展示如何在uni-app中支持暗黑模式。
1. 在App.vue
中设置全局CSS变量
首先,在App.vue
中定义全局的CSS变量,用于存储主题颜色。
<style lang="scss">
:root {
--bg-color: #ffffff;
--text-color: #000000;
/* 当启用暗黑模式时,这些变量将被覆盖 */
--dark-bg-color: #000000;
--dark-text-color: #ffffff;
}
@media (prefers-color-scheme: dark) {
:root {
--bg-color: var(--dark-bg-color);
--text-color: var(--dark-text-color);
}
}
</style>
2. 在组件中使用CSS变量
接下来,在组件中使用这些CSS变量来定义样式。
<template>
<view class="container">
<text class="title">Hello, uni-app!</text>
<button @click="toggleTheme">Toggle Theme</button>
</view>
</template>
<script>
export default {
data() {
return {
isDarkMode: window.matchMedia('(prefers-color-scheme: dark)').matches
};
},
methods: {
toggleTheme() {
this.isDarkMode = !this.isDarkMode;
document.documentElement.style.setProperty('--bg-color', this.isDarkMode ? '#000000' : '#ffffff');
document.documentElement.style.setProperty('--text-color', this.isDarkMode ? '#ffffff' : '#000000');
}
}
};
</script>
<style lang="scss" scoped>
.container {
background-color: var(--bg-color);
color: var(--text-color);
padding: 20px;
}
.title {
font-size: 24px;
}
</style>
3. 处理用户手动切换主题
上面的代码处理了系统级别的暗黑模式,但你也可以添加一个按钮让用户手动切换主题。通过修改CSS变量的值,可以实现主题的切换。
注意:在真实项目中,你可能希望将这些设置持久化到本地存储(如localStorage
),以便在用户重新打开应用时保持他们的主题选择。
4. 持久化主题设置(可选)
你可以使用localStorage
来保存用户的主题偏好。
methods: {
toggleTheme() {
this.isDarkMode = !this.isDarkMode;
localStorage.setItem('theme', this.isDarkMode ? 'dark' : 'light');
// 更新CSS变量
this.updateTheme();
},
updateTheme() {
const theme = localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
this.isDarkMode = theme === 'dark';
document.documentElement.style.setProperty('--bg-color', this.isDarkMode ? '#000000' : '#ffffff');
document.documentElement.style.setProperty('--text-color', this.isDarkMode ? '#ffffff' : '#000000');
},
mounted() {
this.updateTheme();
}
}
这样,你的uni-app应用就能够支持暗黑模式,并且用户可以通过按钮手动切换主题。