HarmonyOS深色模式适配实战——主题切换与WCAG对比度标准

技术栈:HarmonyOS 5.0 + ArkTS + AppStorage

适用场景:应用主题切换、无障碍适配、华为应用市场审核


前言

深色模式已成为现代应用的标配功能。华为应用市场审核对深色模式有严格要求,所有文字必须清晰可见。本文将介绍如何实现符合WCAG标准的深色模式适配。

一、WCAG对比度标准

WCAG(Web Content Accessibility Guidelines)定义了文字对比度标准:

级别 正常文本 大文本
AA级 ≥ 4.5:1 ≥ 3:1
AAA级 ≥ 7:1 ≥ 4.5:1

二、主题颜色定义

2.1 浅色主题

typescript 复制代码
export const LightTheme: ThemeColors = {
  pageBg: '#F8F9FA',
  cardBg: '#FFFFFF',
  cardBgSecondary: '#F5F5F5',
  
  // 文字色 - 符合WCAG标准
  textPrimary: '#1A1A1A',      // 对比度 16.1:1
  textSecondary: '#595959',    // 对比度 7.0:1
  textTertiary: '#737373',     // 对比度 4.6:1
  
  divider: '#EEEEEE',
  border: '#E5E5E5',
  buttonBg: '#F0F0F0',
  shadowColor: 'rgba(0, 0, 0, 0.08)',
};

2.2 深色主题

typescript 复制代码
export const DarkTheme: ThemeColors = {
  pageBg: '#121212',
  cardBg: '#1E1E1E',
  cardBgSecondary: '#2A2A2A',
  
  // 文字色 - 符合WCAG标准
  textPrimary: '#FFFFFF',      // 对比度 15.3:1
  textSecondary: '#CCCCCC',    // 对比度 9.7:1
  textTertiary: '#999999',     // 对比度 5.1:1
  
  divider: '#333333',
  border: '#404040',
  buttonBg: '#2A2A2A',
  shadowColor: 'rgba(0, 0, 0, 0.3)',
};

2.3 主题接口定义

typescript 复制代码
export interface ThemeColors {
  pageBg: string;
  cardBg: string;
  cardBgSecondary: string;
  textPrimary: string;
  textSecondary: string;
  textTertiary: string;
  divider: string;
  border: string;
  buttonBg: string;
  shadowColor: string;
}

三、主题管理器

typescript 复制代码
export class ThemeManager {
  private static isDarkMode: boolean = false;
  private static listeners: Array<(isDark: boolean) => void> = [];

  static setDarkMode(isDark: boolean): void {
    ThemeManager.isDarkMode = isDark;
    ThemeManager.listeners.forEach(listener => listener(isDark));
  }

  static getIsDarkMode(): boolean {
    return ThemeManager.isDarkMode;
  }

  static getTheme(): ThemeColors {
    return ThemeManager.isDarkMode ? DarkTheme : LightTheme;
  }

  static addListener(listener: (isDark: boolean) => void): void {
    ThemeManager.listeners.push(listener);
  }

  static removeListener(listener: (isDark: boolean) => void): void {
    const index = ThemeManager.listeners.indexOf(listener);
    if (index > -1) ThemeManager.listeners.splice(index, 1);
  }
}

四、页面中使用主题

4.1 使用AppStorage实现全局状态

typescript 复制代码
@Entry
@Component
struct MainPage {
  @StorageLink('appDarkMode') isDarkMode: boolean = true;
  
  getBgColor(): string { 
    return this.isDarkMode ? '#0D1117' : '#F5F5F5'; 
  }
  
  getTextPrimary(): string { 
    return this.isDarkMode ? '#FFFFFF' : '#1A1A1A'; 
  }
  
  getTextSecondary(): string { 
    return this.isDarkMode ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.6)'; 
  }

  private toggleTheme(): void {
    this.isDarkMode = !this.isDarkMode;
    AppStorage.setOrCreate('appDarkMode', this.isDarkMode);
    PreferencesUtil.putBoolean('app_dark_mode', this.isDarkMode);
  }

  build() {
    Column() {
      Text('标题')
        .fontSize(24)
        .fontColor(this.getTextPrimary())
      
      Text('副标题')
        .fontSize(14)
        .fontColor(this.getTextSecondary())
      
      Button('切换主题')
        .onClick(() => this.toggleTheme())
    }
    .backgroundColor(this.getBgColor())
  }
}

4.2 跟随系统主题

typescript 复制代码
import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant';

@Entry
@Component
struct SettingsPage {
  @StorageProp('currentColorMode') @Watch('onColorModeChange') 
  currentColorMode: number = ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;
  
  @State themeMode: string = 'system'; // 'system' | 'light' | 'dark'

  onColorModeChange(): void {
    if (this.themeMode === 'system') {
      const isDark = this.currentColorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK;
      AppStorage.setOrCreate('appDarkMode', isDark);
    }
  }

  private applyThemeMode(): void {
    let isDark: boolean;
    if (this.themeMode === 'system') {
      isDark = this.currentColorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK;
    } else {
      isDark = this.themeMode === 'dark';
    }
    AppStorage.setOrCreate('appDarkMode', isDark);
    PreferencesUtil.putString('theme_mode', this.themeMode);
  }
}

五、对比度检查工具

推荐使用在线工具检查颜色对比度:

六、避坑指南

  1. 华为审核要求:深色模式下所有文字必须清晰可见
  2. @StorageLink vs @StorageProp:前者双向绑定,后者只读
  3. 颜色透明度 :使用rgba()时注意透明度对对比度的影响
  4. 图标适配:深色模式下图标也需要适配

总结

本文介绍了HarmonyOS深色模式的完整实现方案,包括符合WCAG标准的颜色定义、主题管理器、页面使用方法等。正确的深色模式适配不仅能通过应用市场审核,还能提升用户体验。

相关推荐
柠果9 小时前
HarmonyOS权限管理实战——麦克风、震动等敏感权限申请
harmonyos
2401_8604947011 小时前
在React Native中实现鸿蒙跨平台开发中开发一个运动类型管理系统,使用React Navigation设置应用的导航结构,创建一个堆栈导航器
react native·react.js·harmonyos
hahjee11 小时前
diffutils文件对比:鸿蒙PC上的diff工具集
华为·harmonyos
2401_8603195211 小时前
react-native-calendarsReact Native库来帮助你处理日期和时间,实现鸿蒙跨平台开发日历组件
react native·react.js·harmonyos
赵财猫._.11 小时前
React Native鸿蒙开发实战(九):复杂业务场景实战与架构设计
react native·react.js·harmonyos
ifeng091812 小时前
uniapp开发鸿蒙:跨端兼容与条件编译实战
华为·uni-app·harmonyos
ifeng091812 小时前
uniapp开发鸿蒙:常见问题与踩坑指南
华为·uni-app·harmonyos
2401_8604947012 小时前
如何在React Native中实现鸿蒙跨平台开发任务列表页面在很多应用中都是一个常见的需求,比如待办事项列表、购物车列表等
react native·react.js·harmonyos
XHW___00112 小时前
鸿蒙webrtc编译
华为·webrtc·harmonyos