ArkUI 深浅色模式:局部预览,不冒充全局切换

举报
蓝瘦的蜕变 发表于 2026/09/24 08:17:02 2026/09/24
【摘要】 深浅色适配不是把白底改成黑底。页面里的文字、边框、按钮和状态反馈都要重新检查对比度和语义。 本篇边界 这篇只做页面局部预览,不调用全局 setColorMode,也不改应用级主题策略。真实项目里,全局深浅色切换应由产品策略、系统设置和应用配置一起决定。 WithTheme 只改变主题资源的解析方式;硬编码十六进制颜色不

ArkUI 深浅色模式:局部预览,不冒充全局切换

深浅色适配不是把白底改成黑底。页面里的文字、边框、按钮和状态反馈都要重新检查对比度和语义。

本篇边界

这篇只做页面局部预览,不调用全局 setColorMode,也不改应用级主题策略。真实项目里,全局深浅色切换应由产品策略、系统设置和应用配置一起决定。

WithTheme 只改变主题资源的解析方式;硬编码十六进制颜色不会跟着系统深浅色变化。预览卡片读取 resources/base/element/color.json 和 resources/dark/element/color.json 中的同名 app.color 资源。

交互预期

  • 点击“跟随系统 / 固定浅色 / 固定深色”,页面中间的预览区域会切换显示。
  • “跟随系统”会按设备当前深浅色解析 color.json 资源;如果设备当前就是浅色,它看起来会接近固定浅色。
  • 下方状态文本会说明当前只是局部预览,没有修改应用全局模式。

Builder 刷新规则

本页已完成 @Builder 参数刷新检阅。模式按钮不再使用 modeButton(item, index) 多参数 Builder,改为 modeButton(index),在 Builder 内部读取 this.modes[index] 和 this.currentIndex。

完整示例代码

class ProductColorModeItem {
  label: string
  desc: string
  mode: ThemeColorMode

  constructor(label: string, desc: string, mode: ThemeColorMode) {
    this.label = label
    this.desc = desc
    this.mode = mode
  }
}

@Entry
@Component
struct ArkUIColorModeDemo {
  @State currentIndex: number = 0
  @State feedback: string = '当前只演示页面局部深浅色,不修改应用全局模式。'

  private modes: ProductColorModeItem[] = [
    new ProductColorModeItem('跟随系统', '卡片读取 color.json,随设备当前深浅色变化。', ThemeColorMode.SYSTEM),
    new ProductColorModeItem('固定浅色', '同一组 app.color 资源被固定解析为浅色。', ThemeColorMode.LIGHT),
    new ProductColorModeItem('固定深色', '同一组 app.color 资源被固定解析为深色。', ThemeColorMode.DARK)
  ]

  private currentMode(): ProductColorModeItem {
    return this.modes[this.currentIndex]
  }

  @Builder
  previewSectionTitle() {
    Column({ space: 6 }) {
      Text('局部预览')
        .fontSize(19)
        .fontWeight(FontWeight.Bold)
        .fontColor($r('app.color.color_mode_text_primary'))
      Text('WithTheme 需要配合 color.json 资源使用,固定十六进制颜色不会随模式变化。')
        .fontSize(13)
        .fontColor($r('app.color.color_mode_text_secondary'))
        .lineHeight(20)
    }
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }

  @Builder
  validationSectionTitle() {
    Column({ space: 6 }) {
      Text('验收重点')
        .fontSize(19)
        .fontWeight(FontWeight.Bold)
        .fontColor($r('app.color.color_mode_text_primary'))
      Text('深浅色不是只反转背景,还要检查文字、边框、按钮和状态反馈。')
        .fontSize(13)
        .fontColor($r('app.color.color_mode_text_secondary'))
        .lineHeight(20)
    }
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }

  @Builder
  modeButton(index: number) {
    Button(this.modes[index].label)
      .height(42)
      .layoutWeight(1)
      .fontSize(14)
      .fontColor(this.currentIndex === index ? '#FFFFFF' : '#334155')
      .backgroundColor(this.currentIndex === index ? '#2563EB' : '#E5E7EB')
      .onClick(() => {
        const item = this.modes[index]
        this.currentIndex = index
        if (item.mode === ThemeColorMode.SYSTEM) {
          this.feedback = '已切换预览:跟随系统。卡片读取 color.json,会按设备当前深浅色解析。'
        } else {
          this.feedback = `已切换预览:${item.label}。这只是局部主题演示,没有调用全局 setColorMode。`
        }
      })
  }

  @Builder
  previewPanel() {
    WithTheme({ colorMode: this.currentMode().mode }) {
      Column({ space: 14 }) {
        Text(this.currentMode().label)
          .fontSize(22)
          .fontWeight(FontWeight.Bold)
          .fontColor($r('app.color.color_mode_text_primary'))
        Text(this.currentMode().desc)
          .fontSize(14)
          .fontColor($r('app.color.color_mode_text_secondary'))
          .lineHeight(22)
        Row({ space: 10 }) {
          Text('主按钮')
            .fontSize(14)
            .fontColor($r('app.color.color_mode_button_text'))
            .padding({ left: 12, right: 12, top: 8, bottom: 8 })
            .backgroundColor($r('app.color.color_mode_button_background'))
            .borderRadius(8)
          Text('次要信息')
            .fontSize(14)
            .fontColor($r('app.color.color_mode_text_primary'))
            .padding({ left: 12, right: 12, top: 8, bottom: 8 })
            .backgroundColor($r('app.color.color_mode_chip_background'))
            .border({ width: 1, color: $r('app.color.color_mode_border') })
            .borderRadius(8)
        }
        .width('100%')
      }
      .width('100%')
      .padding(18)
      .borderRadius(16)
      .backgroundColor($r('app.color.color_mode_panel_background'))
      .border({ width: 1, color: $r('app.color.color_mode_border') })
      .alignItems(HorizontalAlign.Start)
    }
  }

  build() {
    Scroll() {
      Column({ space: 18 }) {
        Text('ArkUI 深浅色模式')
          .fontSize(26)
          .fontWeight(FontWeight.Bold)
          .fontColor($r('app.color.color_mode_text_primary'))
          .width('100%')
        Text('先把应用深浅色适配的边界讲清楚:页面可以做局部预览,真正修改全局模式要放到应用级策略里。')
          .fontSize(14)
          .fontColor($r('app.color.color_mode_text_secondary'))
          .lineHeight(22)
          .width('100%')

        this.previewSectionTitle()
        Row({ space: 8 }) {
          this.modeButton(0)
          this.modeButton(1)
          this.modeButton(2)
        }
        .width('100%')

        this.previewPanel()

        Text(this.feedback)
          .width('100%')
          .fontSize(14)
          .fontColor($r('app.color.color_mode_text_primary'))
          .lineHeight(22)
          .padding(12)
          .backgroundColor($r('app.color.color_mode_chip_background'))
          .borderRadius(10)

        this.validationSectionTitle()
      }
      .width('100%')
      .padding(20)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor($r('app.color.color_mode_page_background'))
  }
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。