uni-app 实现暗黑模式/夜间模式/深色模式/暗黑主题(DarkMode)的几种方法

本文方法已经过时,官方最新方法:

https://uniapp.dcloud.net.cn/tutorial/darkmode.html

https://ask.dcloud.net.cn/article/36995

简介:

uniapp 暗黑模式适配主要包括三部分,一部分是应用中的页面,另一部分是特定功能弹出系统原生界面(如alert提示框)和安全区域外背景颜色,下面会详细说明分别如何适配。

方法一:官方方法,只能适配 ios

这个方法是官方给的,但暂时只能适配 ios,地址:https://ask.dcloud.net.cn/article/36995

官方给的方法主要是靠 plus.navigator.getUIStyle获取当前系统外观模式,uniapp相关的系统组件库会自动使用暗黑模式。

页面上需要使用类似如下的CSS,实现:

@media (prefers-color-scheme: dark){  
    .content {  
        background-color: #1B1C1E;  
        color: white;  
    }  
}


方法二:

在每个页面的 onshow() 以后,使用 uni.setNavigationBarColor() 和 uni.setTabBarStyle() 设置顶部和底部导航条的配色。

// 暗黑模式处理函数
export function darkModeInit(){
  const store = mainStore();
  var isDarkMode = store.isDarkMode;
  
  // 日间模式颜色
  var navigationBarOption = { frontColor: '#000000', backgroundColor: '#ffffff' };
  var tabBarStyleOption = { color: '#71768c', selectedColor: '#1b65ba', backgroundColor: '#FFFFFF' };
  
  // 夜间模式颜色
  if(isDarkMode == true){
    navigationBarOption = { frontColor:'#ffffff', backgroundColor: '#000000' };
    tabBarStyleOption = { color: '#7e858f', selectedColor: '#b5c0d5', backgroundColor: '#333333' };
  }
  
  uni.setNavigationBarColor({
    frontColor: navigationBarOption.frontColor,
    backgroundColor: navigationBarOption.backgroundColor,
    animation: {
      duration: 0,
      timingFunc: 'easeIn'
    },
    success(e){
      // console.log("设置顶部导航背景色成功",e);
    },
    fail(e) {
      // console.log('设置顶部导航失败: ', e.errMsg);
    }
  });

  uni.setTabBarStyle({
    color: tabBarStyleOption.color,
    selectedColor: tabBarStyleOption.selectedColor,
    backgroundColor: tabBarStyleOption.backgroundColor,
    borderStyle: 'black',
    success(e){
      // console.log("设置底部标签页背景色成功",e);
    },
    fail(e) {
      // console.log('设置底部标签页失败: ', e.errMsg);
    }
  });
}


然后就是修改页面背景色,在 Web 页面,一般定义 CSS 变量 :root { --bg-color: #fff;} 和 :root.dark { --bg-color: #000;} ,然后切换 .dark 类实现夜间模式切换。参考:https://javascript.net.cn/articles/820

遇到的问题

:root 这个 CSS 伪类匹配文档树的根元素。对于 HTML 来说,:root 表示 <html> 元素,除了优先级更高之外,与 html 选择器相同。但是,小程序中无法直接操作 body 的 class 列表。

这种方法暂时遇到一个问题,在 uniapp 中,page 相当于 body 节点,例如:

/* 设置页面背景颜色,使用 scoped 会导致失效 */
page {
  background-color: #ccc;
}


如果使用媒体查询,只能适配 IOS:

@media (prefers-color-scheme: dark) {
  body { background: #333; color: #eee; }
}


考虑过通过 JS 修改 page { background: var(--bg-color); } 中的颜色变量:

document.documentElement.style.setProperty('--bg-color', color);

暂未找到 uniapp 中的修改方法:https://uniapp.dcloud.io/api/ui/nodes-info.html


解决方法

暂时用了一种不优雅的方案,放弃切换 :root 的 .dark 类,而是在每个 vue 页面,最外层的 view 里使用

<view class="container" :class="{'dark-mode':store.isDarkMode}"></view>


备注:

可以使用 uni.setBackgroundColor(OBJECT) 动态设置窗口的背景色。但是只支持微信小程序等部分小程序,不支持 APP 和 H5 等。


参考:

https://uniapp.dcloud.io/api/ui/bgcolor.html

https://uniapp.dcloud.io/tutorial/syntax-css.html#内联样式

https://developer.mozilla.org/zh-CN/docs/Web/CSS/:root

https://www.jianshu.com/p/8e4a7f124e49

https://www.ruletree.club/archives/2610/

https://blog.csdn.net/jijunqing321/article/details/117435173

修改时间 2024-03-05

声明:本站所有文章和图片,如无特殊说明,均为原创发布。商业转载请联系作者获得授权,非商业转载请注明出处。
随机推荐
CRSF 跨站脚本攻击已死,使用 Same-Site Cookies 来防范 CSRF
Node.js 实现 RBAC 权限模型
WordPress 文章置顶循环
HTML input checkbox 复选按钮
Node.js fs 文件系统模块
WordPress 添加文章自定义字段
JavaScript 字符串详细介绍
WordPress 数据库表结构