uni-app OS设置自动启用深色模式时始终仅能取得light模式

发布于 1周前 作者 yibo5220 来自 Uni-App

uni-app OS设置自动启用深色模式时始终仅能取得light模式

信息类别 详细信息
产品分类 uniapp/App
PC开发环境操作系统 Windows
PC开发环境操作系统版本号 win10
HBuilderX类型 正式
HBuilderX版本号 4.29
手机系统 Android
手机系统版本号 Android 10
手机厂商 zte
手机机型 中兴远航10 5G
页面类型 vue
vue版本 vue3
打包方式 云端
项目创建方式 HBuilderX

操作步骤:

  1. manifest.json里已配置app-plus节点下的darkmode为true
  2. onLaunch里监听theme:
    uni.onThemeChange((res)=>{
        const {osTheme , theme} = uni.getSystemInfoSync()
        uni.showModal({
            content:`onThemeChange res.theme=${res.theme} ; systemInfo.osTheme=${osTheme}  ; systemInfo.theme=${theme}`
        })
    })
    
  3. index里设置暗黑模式为跟随系统:
    plus.nativeUI.setUIStyle('auto')
    
  4. 运行含有上述程序的APP后,返回OS桌面。
  5. 在操作系统的「设置-显示」里,设置深色模式为自动启用。
  6. 在保持深色模式自动启用的同时,点击“立即启用” 或者 调整系统时间使之临近预设的启用时间。
  7. 待确认OS已切换到深色模式后,返回APP,观察showModal弹出的内容,查看onThemeChange的回调参数里的theme 和 此时通过getSystemInfoSync获得的osTheme、theme是否与实际情况一致。

预期结果:

取值应为dark,且showModal的弹窗应为深色风格。

实际结果:

取值实为light,且showModal的弹窗仍为浅色风格。

bug描述:

测了android10、android14,在设置了plus.nativeUI.setUIStyle(‘auto’)之后,发现: 当设置OS的深色模式为自动启用时,再手动切换浅色/深色模式或者待OS成功自动启用深色模式,uniapp通过uni.onThemeChange取得的theme值 或 通过uni.getSystemInfo取得的osTheme、theme值始终为light,且原生界面也无法如期切换到暗黑模式。 若不设置OS的深色模式为自动启用,则上述取值是正常的。


12 回复

os的主题触发change的时候,你的应用处于开启状态吗? 如果此时你的应用并未开启,那肯定接受不到通知,等你再启动就晚了。 change事件是一个辅助,启动的时候还得自己判断下当前的主题


你好,应用是处于开启状态的。os的深色模式不管是否打开自动启用,都能收到通知,但是,在打开自动启用的情况下,应用收到的通知总是light。

我再配图说明一下使用 hello-darkmode示例工程 复现该问题的步骤。
一、首次运行hello-darkmode 【表现正常】
此时系统尚未启用深色模式(见下图)

hello-darkmode显示当前主题为:auto (见下图)

二、设置自动启用深色模式,启用时间为11:20

三、保持hello-darkmode在后台运行,熄屏,直到11:20。
四、 11:20时,打开手机,打开hello-darkmode和微信,发现均未切换模式,可能均未获取到模式切换消息(这可能是系统的机制问题,再次熄屏,再次打开就会触发,此处不深究)
五、 再次熄屏,再次打开,发现微信已切到深色模式,hello-darkmode识别到模式却为light。【异常】

以下再补充一个更简单的使用hello-darkmode示例工程的复现流程,实际就是楼上的复现的极简版。
一、打开系统深色模式的自动启用,并同时直接把深色模式启用。

二、下图获取到的主题始终为light

请关注一下此问题,谢谢。

请关注一下此问题,谢谢。

请关注一下此问题,谢谢。

请关注一下此问题,谢谢。

请关注一下此问题,谢谢。

请关注一下此问题,谢谢。

在uni-app中,处理系统深色模式(Dark Mode)和浅色模式(Light Mode)的切换通常需要依赖uni.getSystemInfoSync方法来获取系统当前的主题模式,并结合CSS变量或类名来控制页面的样式。如果你发现即使在系统设置为自动启用深色模式时,uni-app始终只能取得light模式,可能是因为uni-app的配置或代码处理逻辑有误。

以下是一个基本的代码案例,展示了如何在uni-app中检测并响应系统主题模式的变化:

  1. App.vue中初始化主题模式
<script>
export default {
  onLaunch() {
    this.updateTheme();
    // 监听系统主题变化(如果平台支持)
    if (typeof window !== 'undefined' && 'matchMedia' in window) {
      const mediaQueryList = window.matchMedia('(prefers-color-scheme: dark)');
      mediaQueryList.addEventListener('change', this.updateTheme);
    }
  },
  methods: {
    updateTheme() {
      const systemInfo = uni.getSystemInfoSync();
      let theme = 'light';
      if (systemInfo.theme === 'dark' || 
          (typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
        theme = 'dark';
      }
      // 设置全局样式变量或类名
      uni.setStorageSync('theme', theme);
      this.$set(uni.$store.state, 'theme', theme); // 假设你使用了Vuex
      document.documentElement.setAttribute('data-theme', theme);
    }
  }
}
</script>

<style>
/* 定义基础样式 */
:root {
  --bg-color-light: #ffffff;
  --bg-color-dark: #333333;
  --text-color-light: #000000;
  --text-color-dark: #ffffff;
}

[data-theme="light"] {
  background-color: var(--bg-color-light);
  color: var(--text-color-light);
}

[data-theme="dark"] {
  background-color: var(--bg-color-dark);
  color: var(--text-color-dark);
}
</style>
  1. 在组件中使用主题

确保你的组件样式可以响应data-theme属性的变化,无需在每个组件中单独处理主题切换逻辑。

  1. 注意事项
  • 上述代码假设你在App.vue中处理主题切换,并通过document.documentElement.setAttribute设置全局的data-theme属性。
  • 如果你使用Vuex管理状态,可以在Vuex中存储当前主题,并在组件中通过计算属性访问。
  • uni.getSystemInfoSync获取的系统信息可能不包含theme字段(取决于uni-app版本和平台支持),因此建议使用window.matchMedia作为备用方案。
  • 确保你的页面和组件样式使用了CSS变量,以便能够根据data-theme属性动态调整样式。
回到顶部