前言

沉浸材质放到纯色背景上时,可读性通常不难处理。背景偏暗,前景使用亮一些的文字;背景偏亮,文字再压暗一些,页面很快就能达到一个比较稳定的状态。

真正麻烦的是背景开始变化以后。搜索框可能压在一张大图上,顶部工具栏下面的列表还在持续滚动,浮动操作区甚至会同时跨过深色、浅色和高饱和区域。同一段文字在左侧看起来很清楚,移动几十个像素以后,对比度可能马上下降。

我在这类页面里最先关注的通常有两层:一层是材质本身能不能适当压住背景,另一层是材质里的文字和图标能不能继续保持清楚。

materialColor 可以给材质增加一层带透明度的颜色,帮助降低复杂背景的干扰;colorInvert 则负责材质节点子树中的前景颜色适配。不过,colorInvert 的条件比单纯写一个 true 要严格得多。当前 API 明确要求材质足够薄,同时只对部分颜色属性使用特定资源值的场景生效,而且它的显示效果还限定在高档和中档算力设备上。

这几个条件放在一起以后,自动反色更适合作为一项“带前提的系统能力”来使用。大家看到 colorInvert: true 以后,还需要继续检查材质厚度、颜色资源、当前组件以及运行设备。

所以,这次我仍然会把页面做得尽量简单:同一套复杂背景、两张尺寸一致的 THIN 卡片,一张关闭 colorInvert,另一张打开。页面还会提供一个辅助赋色开关,用来观察背景越来越复杂以后,增加半透明 materialColor 会不会让内容更稳定。

目前我的测试设备还没有 HarmonyOS 7 实机测试权限,因此当前示例先在模拟器中运行。模拟器可以帮助大家核对接口、页面结构和基础显示,自动反色的实际触发程度仍要优先在具备权限的真机上复核。

一、打开 colorInvert 之前,先确认它真正作用在哪里

colorInvertImmersiveOptions 中的一个布尔参数。设置为 true 后,系统会尝试让设置了材质对象的节点子树根据材质与背景关系进行颜色适配。它从 API 26.0.0 开始提供。

代码本身很短:

new uiMaterial.ImmersiveMaterial({
  style: uiMaterial.ImmersiveStyle.THIN,
  colorInvert: true
});

真正容易出问题的是这段代码周围的条件。

材质首先要足够薄

当前 API 对 colorInvert 的说明很明确。开启自动反色以后,只有材质参数足够薄时才会进入相应的适配路径,材质样式至少需要达到 THINULTRA_THIN。系统沉浸光感强度也会影响触发条件,材质越薄、系统配置越强,越容易满足反色要求。

因此,这次实验统一使用:

style: uiMaterial.ImmersiveStyle.THIN

这样既保留了比较明显的背景信息,也给自动反色留出了官方要求的材质条件。

如果页面已经使用 REGULARTHICKULTRA_THICK,此时把 colorInvert 打开,也不能据此预期和 THIN 相同的反色表现。

$r() 这一层还要继续往下看

颜色条件比材质厚度更容易被忽略。

自动反色只会对部分支持的颜色属性在设置特殊资源值时生效。也就是说,仅仅看到代码里使用了 $r(),还不能直接判断已经满足了 colorInvert 的资源条件。

这也是为什么我不建议再用下面这种自定义资源作为“自动反色一定会触发”的证据:

.fontColor(
  $r('app.color.custom_text_color')
)

app.color 本身当然可以正常承担应用颜色资源和深浅色适配,HarmonyOS 也支持在 basedark 等资源目录中为同一个资源 ID 配置不同值。可 colorInvert 还有一层“特殊资源值”的约束,两件事需要分开理解。

实验页面里可以先使用系统提供的文本资源,避免继续硬编码颜色:

Text('复杂背景可读性')
  .fontColor(
    $r('sys.color.ohos_id_color_text_primary')
  )

$r('sys.color.ohos_id_color_text_primary') 是官方深浅色适配文档给出的系统文本资源示例,可以随系统颜色模式加载相应资源值。至于当前 SDK 中哪些资源属于 colorInvert 所要求的特殊资源,仍然应该以当前 API 文档对应的资源表和实际设备结果为准。

这样处理会稳一些:系统资源负责正常的颜色体系,colorInvert 负责满足条件后的材质背景适配,两层能力各自承担自己的任务。

哪些前景属性进入了 colorInvert 的支持范围

当前 API 已经列出了明确的属性范围,里面不只有 Text。比较常用的几个入口可以先记下来:

组件 与自动反色相关的属性
Text fontColor
Button fontColor
SymbolGlyph fontColor
Image fillColor
Search placeholderColorfontColor、搜索图标颜色、取消图标颜色、光标颜色
TabContent 使用 BottomTabBarStyle 时的文本与图标颜色

当前最新 API 文档还继续列出了 Chip、ChipGroup、TextArea、TextInput、SegmentButton、Swiper 等相关颜色属性,因此大家在这些组件上处理自动反色时,也应该先检查具体属性是否进入官方支持列表。

这一篇没有必要把所有组件都塞进 Demo。Text.fontColor 已经足够完成最小实验,其他组件可以沿用同样的检查顺序:先看组件和属性是否支持,再看资源条件,最后看设备结果。

设备本身也是 colorInvert 的一项条件

还有一个限制需要单独记住:colorInvert 的显示效果当前只对高档和中档算力设备生效。设备的高、中、低算力分档由设备厂商在系统中决定。

这一点和模拟器测试关系很大。

模拟器里代码能够正常运行,说明接口调用和页面链路已经走通;页面没有出现明显自动反色时,还需要考虑当前环境是否能够完整呈现这项设备相关效果。

所以,碰到自动反色不明显时,可以按下面的顺序检查:

THIN / ULTRA_THIN
↓
组件属性位于 colorInvert 支持范围
↓
使用当前 API 要求的特殊资源条件
↓
保持沉浸光感系统设置一致
↓
确认当前设备能力

条件理顺以后,再讨论 materialColor 就会自然很多。因为自动反色主要处理前景,而复杂背景本身仍然可能太抢眼。

二、把复杂背景和反色状态放在同一页面里

条件知道得再多,真正进入页面以后还是要看实际效果。

我比较喜欢把 colorInvert = falsecolorInvert = true 同时放出来。两张卡片保持相同尺寸、相同位置逻辑、相同背景和相同文字资源。这样页面一打开,就能直接比较两种状态。

同时,背景也不需要准备很多真实图片。图片内容本身变化太多,很容易把问题带偏。当前实验准备三组可切换背景,已经足够覆盖常见干扰:

深浅分区
彩色分区
高对比纹理

深浅分区最适合检查基础明暗变化;彩色分区可以看高饱和背景;高对比纹理再加入深浅色块和文字,让背景信息更接近真实图片或复杂列表。

两张卡片只改变 colorInvert

关闭自动反色的材质:

private readonly normalMaterial: uiMaterial.Material =
  new uiMaterial.ImmersiveMaterial({
    style: uiMaterial.ImmersiveStyle.THIN,
    colorInvert: false
  });

开启自动反色的材质:

@State private adaptiveMaterial: uiMaterial.Material =
  new uiMaterial.ImmersiveMaterial({
    style: uiMaterial.ImmersiveStyle.THIN,
    colorInvert: true
  });

两张卡片内部使用同一套系统文本资源:

Text('复杂背景可读性')
  .fontColor(
    $r('sys.color.ohos_id_color_text_primary')
  )

这里的对比重点是,两张卡片只有 colorInvert 状态不同。

不过,页面上看到颜色变化以后,还不能只凭 $r() 形式就把结果全部归因于自动反色。系统文本资源本身也会承担深浅色适配;colorInvert 是否真正进入自动反色路径,还要结合当前 SDK 的特殊资源规则、设备分档和实际显示一起判断。

这种实验方式反而更适合真实项目。大家可以看到当前环境到底呈现了什么,再去检查对应条件,而不会因为代码中出现 colorInvert: true 就提前假设结果。

页面顶部继续保留 MaterialState

实验开始之前还要先确认应用状态。

getMaterialInfo() 可以读取 module.json5 中的材质配置。DISABLE 状态会禁止应用中的所有沉浸式系统材质,即使主动设置 ImmersiveMaterial 也不会生效;DEFAULTENABLE 都允许普通组件主动使用材质。

所以页面顶部继续保留:

MaterialState
DEFAULT / ENABLE / DISABLE

如果这里已经显示 DISABLE,下面的反色实验就没有继续比较的意义,应用状态应该先处理好。

背景越来越乱时,可以再加一层 materialColor

自动反色关注的是前景颜色,背景的信息密度依然可能很高。

例如,一张卡片下面刚好出现亮色图片、高对比线条和多行文字,即使前景颜色已经能够适配,背景本身仍然会抢走很多注意力。

这时可以给开启自动反色的卡片再增加一层半透明 materialColor

new uiMaterial.ImmersiveMaterial({
  style: uiMaterial.ImmersiveStyle.THIN,
  materialColor: '#4DFFFFFF',
  colorInvert: true
});

materialColor 会在材质滤镜上混合一层颜色。官方 FAQ 明确提醒,这个颜色需要带透明度;纯不透明颜色会遮挡材质滤镜效果。

我通常会从比较轻的透明度开始。背景仍然保留,但视觉干扰被压低一些,这种状态更适合搜索框和悬浮工具栏。颜色太重以后,材质很容易逐渐变成普通色块。

页面里的“辅助赋色”开关就是为了快速观察这一层变化:

colorInvert = true
↓
打开辅助 materialColor
↓
观察背景干扰是否下降

三、回到项目以后,可读性可以按背景复杂度逐步处理

实验页面能帮助大家理解条件,真正放回业务界面时,背景往往不会像测试页这样规整。

一张图片可能左边很暗、右边很亮;列表会持续滚动;视频画面也会不断变化。这个时候,我更习惯从最轻的处理方式开始,再根据实际干扰程度逐步增加控制。

背景比较简单时,先依靠正常颜色资源

很多页面其实用不到 colorInvert

普通内容区域只需要跟随系统浅色和深色模式时,继续使用系统资源或 base / dark 资源目录已经足够。HarmonyOS 支持为同一个资源 ID 在不同颜色模式下提供不同值,系统会根据当前模式加载对应资源。

例如:

Text('页面标题')
  .fontColor(
    $r('sys.color.ohos_id_color_text_primary')
  )

这层处理解决的是页面主题。

薄材质跨越变化背景时,再考虑 colorInvert

搜索框、顶部悬浮栏或小面积操作区会持续跨越不同背景时,可以考虑:

new uiMaterial.ImmersiveMaterial({
  style: uiMaterial.ImmersiveStyle.THIN,
  colorInvert: true
});

随后检查该组件实际使用的颜色属性是否位于支持列表,颜色资源是否满足当前 API 的特殊资源要求,并在高档或中档算力真机上验证。

这种情况下,colorInvert 的价值就在于背景发生变化以后,前景还有一条系统适配路径。

背景干扰继续增加,再加入半透明 materialColor

图片、渐变或高对比内容已经明显影响阅读时,可以继续给薄材质加入轻量赋色:

new uiMaterial.ImmersiveMaterial({
  style: uiMaterial.ImmersiveStyle.THIN,
  materialColor: '#4DFFFFFF',
  colorInvert: true
});

这时 materialColor 帮助降低背景视觉强度,colorInvert 继续承担满足条件后的前景颜色适配。

两层配置可以一起使用,不过透明度需要控制。材质赋色过重以后,组件会失去很多通透感;赋色过轻,又可能压不住复杂图片。

信息量继续增加时,可以考虑提高材质厚度

大面积浮层里已经包含标题、正文、按钮和多行选项时,继续保留大量背景信息会让阅读压力越来越高。

REGULARTHICKULTRA_THICK 会逐渐增加材质厚度,其中 THICK 适合菜单等需要较强背景模糊的场景,ULTRA_THICK 更适合弹窗等需要大幅降低背景干扰的区域。

材质加厚以后,页面也要同步调整判断方式。colorInvert 的自动反色条件要求材质至少处于 THINULTRA_THIN 范围,因此厚材质更适合依靠稳定的主题资源和前景颜色体系来保证阅读。

整体可以沿着下面这条路径判断:

普通页面
系统 / 深浅色资源

↓

薄材质跨越变化背景
THIN + colorInvert 条件检查

↓

背景视觉干扰明显
THIN + 半透明 materialColor
+ colorInvert 条件检查

↓

大面积、高信息密度浮层
REGULAR / THICK / ULTRA_THICK
+ 稳定的前景颜色资源

这个顺序对我来说比较实用,因为每一步都对应一个很具体的问题。

页面主题有问题,就先处理资源;背景开始变化,再检查自动反色;背景越来越乱,再加入材质赋色;内容本身已经很多,再提高材质厚度。

深浅色适配和 colorInvert 要各自承担自己的任务

这两个概念放在一起时很容易混淆。

base / dark 资源主要处理应用处于浅色模式或深色模式时应该使用什么颜色。系统资源本身也可以根据设备和颜色模式提供不同值。

colorInvert 则属于沉浸材质参数,它关注材质与当前背景之间的颜色关系,并且具有薄材质、特殊资源、支持属性以及设备算力等额外限制。

把两层职责分开以后,现有项目会更容易维护:

应用浅色 / 深色模式
↓
系统资源、base / dark 资源

复杂背景上的薄沉浸材质
↓
colorInvert

这样普通页面不需要为了沉浸光感改变整套颜色体系,真正需要跨背景显示的组件再额外处理。

总结

复杂背景上的可读性问题,通常很难靠一个参数一次解决。

我更习惯先把页面现有的颜色资源整理好,让普通浅色、深色模式本身稳定。悬浮组件开始跨越变化背景以后,再检查 colorInvert 的条件。

这里有几个条件需要一直放在一起看:材质至少使用 THINULTRA_THIN,前景属性必须位于官方支持范围,颜色还需要满足自动反色要求的特殊资源条件,同时 colorInvert 的显示效果当前只面向高档和中档算力设备。

背景继续变复杂时,可以增加带透明度的 materialColor,先压低底层内容的干扰。组件面积和信息量继续增加以后,再提高材质厚度,让前景拥有更稳定的阅读空间。纯不透明的材质赋色会遮住材质滤镜,因此颜色透明度仍然需要保留。

整个过程可以记成一条很简单的路径:

先处理正常颜色资源
↓
薄材质检查 colorInvert 条件
↓
复杂背景增加半透明 materialColor
↓
信息密度提高后增加材质厚度

当前页面可以在 HarmonyOS 7 模拟器中核对 API 调用、背景切换和基础显示。自动反色涉及特殊资源与设备算力,正式用于项目之前,大家仍应优先在具备 HarmonyOS 7 测试权限的真机上确认最终可读性。

完整代码

当前实验不再增加自定义 app.color 来充当自动反色条件。页面使用官方深浅色适配文档示例中的系统一级文本资源,避免硬编码颜色;colorInvert 是否真正触发,仍需要结合当前 SDK 所要求的特殊资源条件以及实际设备结果判断。

Main.ets

/**
 * HarmonyOS 7 沉浸光感深度实战 06
 *
 * 验证环境:
 * HarmonyOS SDK API 26
 * HarmonyOS 7 模拟器
 */

import { uiMaterial } from '@kit.ArkUI';

@Entry
@Component
struct Main {
  @State private materialStateText: string =
    '当前应用尚未读取状态';

  @State private stateColor: ResourceColor =
    '#68708A';

  /**
   * 0:深浅分区
   * 1:彩色分区
   * 2:高对比纹理
   */
  @State private backgroundMode: number = 0;

  /**
   * 开启后,为自动反色卡片增加半透明辅助赋色。
   */
  @State private tintEnabled: boolean = false;

  /**
   * 对照卡片:
   * 使用 THIN,关闭 colorInvert。
   */
  private readonly normalMaterial: uiMaterial.Material =
    new uiMaterial.ImmersiveMaterial({
      style: uiMaterial.ImmersiveStyle.THIN,
      colorInvert: false
    });

  /**
   * 自动反色实验卡片。
   * 页面根据辅助赋色开关重新创建材质对象。
   */
  @State private adaptiveMaterial: uiMaterial.Material =
    new uiMaterial.ImmersiveMaterial({
      style: uiMaterial.ImmersiveStyle.THIN,
      colorInvert: true
    });

  aboutToAppear(): void {
    this.loadMaterialState();
    this.refreshAdaptiveMaterial();
  }

  /**
   * 读取应用级材质状态。
   * DISABLE 会关闭应用中的沉浸式系统材质。
   */
  private loadMaterialState(): void {
    const info: uiMaterial.MaterialInfo =
      uiMaterial.getMaterialInfo();

    this.materialStateText =
      this.getMaterialStateName(info.state);

    this.stateColor =
      this.getMaterialStateColor(info.state);
  }

  private getMaterialStateName(
    state: uiMaterial.MaterialState
  ): string {
    switch (state) {
      case uiMaterial.MaterialState.DEFAULT:
        return 'DEFAULT';

      case uiMaterial.MaterialState.ENABLE:
        return 'ENABLE';

      case uiMaterial.MaterialState.DISABLE:
        return 'DISABLE';

      default:
        return `未知状态 ${state}`;
    }
  }

  private getMaterialStateColor(
    state: uiMaterial.MaterialState
  ): ResourceColor {
    switch (state) {
      case uiMaterial.MaterialState.DEFAULT:
        return '#5065E8';

      case uiMaterial.MaterialState.ENABLE:
        return '#1A8F5D';

      case uiMaterial.MaterialState.DISABLE:
        return '#C85A3A';

      default:
        return '#68708A';
    }
  }

  /**
   * 辅助赋色开启时加入半透明白色。
   * 关闭时直接省略 materialColor。
   */
  private refreshAdaptiveMaterial(): void {
    if (this.tintEnabled) {
      this.adaptiveMaterial =
        new uiMaterial.ImmersiveMaterial({
          style: uiMaterial.ImmersiveStyle.THIN,
          materialColor: '#4DFFFFFF',
          colorInvert: true
        });
      return;
    }

    this.adaptiveMaterial =
      new uiMaterial.ImmersiveMaterial({
        style: uiMaterial.ImmersiveStyle.THIN,
        colorInvert: true
      });
  }

  @Builder
  private sectionTitle(
    title: string,
    description: string
  ) {
    Column({ space: 4 }) {
      Text(title)
        .fontSize(22)
        .fontWeight(FontWeight.Bold)
        .fontColor('#11182C')
        .width('100%')

      Text(description)
        .fontSize(14)
        .fontColor('#68708A')
        .lineHeight(21)
        .width('100%')
    }
    .alignItems(HorizontalAlign.Start)
    .width('100%')
  }

  @Builder
  private materialStateCard() {
    Row({ space: 12 }) {
      Text('MaterialState')
        .width('42%')
        .fontSize(14)
        .fontColor('#68708A')

      Text(this.materialStateText)
        .layoutWeight(1)
        .fontSize(14)
        .fontWeight(FontWeight.Medium)
        .fontColor(this.stateColor)
        .textAlign(TextAlign.End)
    }
    .width('100%')
    .padding(16)
    .backgroundColor(Color.White)
    .borderRadius(20)
  }

  /**
   * 深浅分区。
   */
  @Builder
  private darkLightBackground() {
    Row() {
      Column({ space: 5 }) {
        Text('DARK')
          .fontSize(22)
          .fontWeight(FontWeight.Bold)
          .fontColor('#99FFFFFF')

        Text('深色区域')
          .fontSize(11)
          .fontColor('#BFFFFFFF')
      }
      .width('50%')
      .height('100%')
      .justifyContent(FlexAlign.Center)
      .alignItems(HorizontalAlign.Center)
      .backgroundColor('#17203A')

      Column({ space: 5 }) {
        Text('LIGHT')
          .fontSize(22)
          .fontWeight(FontWeight.Bold)
          .fontColor('#6617203A')

        Text('浅色区域')
          .fontSize(11)
          .fontColor('#9917203A')
      }
      .layoutWeight(1)
      .height('100%')
      .justifyContent(FlexAlign.Center)
      .alignItems(HorizontalAlign.Center)
      .backgroundColor('#F5E6AE')
    }
    .width('100%')
    .height('100%')
  }

  /**
   * 彩色分区。
   */
  @Builder
  private colorBackground() {
    Row() {
      Column()
        .width('33%')
        .height('100%')
        .backgroundColor('#3958D8')

      Column()
        .width('34%')
        .height('100%')
        .backgroundColor('#A55AD9')

      Column()
        .layoutWeight(1)
        .height('100%')
        .backgroundColor('#F0C34E')
    }
    .width('100%')
    .height('100%')
  }

  /**
   * 高对比纹理。
   * 深浅色块和文字同时出现,
   * 用于增加材质下方的背景信息量。
   */
  @Builder
  private highContrastBackground() {
    Stack() {
      Row() {
        Column()
          .width('17%')
          .height('100%')
          .backgroundColor('#11182C')

        Column()
          .width('17%')
          .height('100%')
          .backgroundColor('#F6F7FB')

        Column()
          .width('17%')
          .height('100%')
          .backgroundColor('#3E5BDB')

        Column()
          .width('17%')
          .height('100%')
          .backgroundColor('#F0C54E')

        Column()
          .width('16%')
          .height('100%')
          .backgroundColor('#913FD2')

        Column()
          .layoutWeight(1)
          .height('100%')
          .backgroundColor('#F6F7FB')
      }
      .width('100%')
      .height('100%')

      Column({ space: 5 }) {
        Text('CONTENT · IMAGE · TEXT')
          .fontSize(13)
          .fontWeight(FontWeight.Bold)
          .fontColor('#FFFFFFFF')
          .maxLines(1)

        Text('01 02 03 · COMPLEX BACKGROUND')
          .fontSize(10)
          .fontColor('#E6FFFFFF')
          .maxLines(1)
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.End)
      .alignItems(HorizontalAlign.Center)
      .padding({
        bottom: 10
      })
    }
    .width('100%')
    .height('100%')
  }

  /**
   * 两张卡片共用同一个背景入口,
   * 保证对照条件一致。
   */
  @Builder
  private comparisonBackground() {
    if (this.backgroundMode === 0) {
      this.darkLightBackground()
    } else if (this.backgroundMode === 1) {
      this.colorBackground()
    } else {
      this.highContrastBackground()
    }
  }

  /**
   * 两张实验卡片共用相同尺寸、背景和文字。
   *
   * 文本使用官方系统文本资源,避免硬编码颜色。
   * colorInvert 是否触发仍需要满足当前 API
   * 对特殊资源和设备能力的完整要求。
   */
  @Builder
  private readabilityCard(
    stateText: string,
    material: uiMaterial.Material
  ) {
    Stack() {
      this.comparisonBackground()

      Column({ space: 8 }) {
        Text('复杂背景可读性')
          .fontSize(19)
          .fontWeight(FontWeight.Bold)
          .fontColor(
            $r('sys.color.ohos_id_color_text_primary')
          )
          .textAlign(TextAlign.Center)
          .width('100%')

        Text(stateText)
          .fontSize(12)
          .fontColor(
            $r('sys.color.ohos_id_color_text_primary')
          )
          .textAlign(TextAlign.Center)
          .width('100%')

        Text('观察文字跨越不同背景时的实际表现')
          .fontSize(12)
          .fontColor(
            $r('sys.color.ohos_id_color_text_primary')
          )
          .textAlign(TextAlign.Center)
          .maxLines(2)
          .width('100%')
      }
      .width('88%')
      .height(116)
      .padding({
        left: 12,
        right: 12
      })
      .backgroundColor(Color.Transparent)
      .borderRadius(26)
      .justifyContent(FlexAlign.Center)
      .alignItems(HorizontalAlign.Center)
      .systemMaterial(material)
    }
    .width('100%')
    .height(168)
    .borderRadius(26)
    .clip(true)
  }

  @Builder
  private backgroundSelector() {
    Column({ space: 10 }) {
      Text('测试背景')
        .fontSize(15)
        .fontWeight(FontWeight.Medium)
        .fontColor('#17203A')
        .width('100%')

      Row({ space: 8 }) {
        Button('深浅')
          .layoutWeight(1)
          .height(38)
          .fontSize(12)
          .fontColor(
            this.backgroundMode === 0
              ? Color.White
              : '#5065E8'
          )
          .backgroundColor(
            this.backgroundMode === 0
              ? '#5065E8'
              : '#EEF1FF'
          )
          .onClick(() => {
            this.backgroundMode = 0;
          })

        Button('彩色')
          .layoutWeight(1)
          .height(38)
          .fontSize(12)
          .fontColor(
            this.backgroundMode === 1
              ? Color.White
              : '#5065E8'
          )
          .backgroundColor(
            this.backgroundMode === 1
              ? '#5065E8'
              : '#EEF1FF'
          )
          .onClick(() => {
            this.backgroundMode = 1;
          })

        Button('高对比')
          .layoutWeight(1)
          .height(38)
          .fontSize(12)
          .fontColor(
            this.backgroundMode === 2
              ? Color.White
              : '#5065E8'
          )
          .backgroundColor(
            this.backgroundMode === 2
              ? '#5065E8'
              : '#EEF1FF'
          )
          .onClick(() => {
            this.backgroundMode = 2;
          })
      }
      .width('100%')
    }
    .width('100%')
    .padding(16)
    .backgroundColor(Color.White)
    .borderRadius(20)
  }

  @Builder
  private tintPanel() {
    Row({ space: 12 }) {
      Column({ space: 4 }) {
        Text('辅助赋色')
          .fontSize(15)
          .fontWeight(FontWeight.Medium)
          .fontColor('#17203A')

        Text(
          '为 colorInvert=true 的卡片增加半透明 materialColor'
        )
          .fontSize(12)
          .fontColor('#747C92')
          .lineHeight(18)
      }
      .layoutWeight(1)
      .alignItems(HorizontalAlign.Start)

      Toggle({
        type: ToggleType.Switch,
        isOn: this.tintEnabled
      })
        .onChange((isOn: boolean) => {
          this.tintEnabled = isOn;
          this.refreshAdaptiveMaterial();
        })
    }
    .width('100%')
    .padding(16)
    .alignItems(VerticalAlign.Center)
    .backgroundColor(Color.White)
    .borderRadius(20)
  }

  build() {
    Scroll() {
      Column({ space: 18 }) {
        Column({ space: 6 }) {
          Text('HarmonyOS 7 沉浸光感')
            .fontSize(28)
            .fontWeight(FontWeight.Bold)
            .fontColor('#11182C')
            .width('100%')

          Text('复杂背景与自动反色')
            .fontSize(16)
            .fontColor('#68708A')
            .width('100%')
        }
        .alignItems(HorizontalAlign.Start)
        .width('100%')

        this.sectionTitle(
          '当前应用状态',
          'DEFAULT 和 ENABLE 可以进行当前材质实验。'
        )

        this.materialStateCard()

        this.sectionTitle(
          '背景条件',
          '切换背景后,两张卡片继续使用相同测试环境。'
        )

        this.backgroundSelector()

        this.sectionTitle(
          '关闭自动反色',
          'THIN 材质保持 colorInvert=false。'
        )

        this.readabilityCard(
          'colorInvert = false',
          this.normalMaterial
        )

        this.sectionTitle(
          '开启自动反色',
          'THIN 材质设置 colorInvert=true。'
        )

        this.readabilityCard(
          this.tintEnabled
            ? 'colorInvert = true · 辅助赋色开'
            : 'colorInvert = true',
          this.adaptiveMaterial
        )

        this.tintPanel()

        Text(
          '模拟器用于核对接口和基础显示,'
            + '自动反色最终效果仍需在真机上复核。'
        )
          .fontSize(13)
          .fontColor('#747C92')
          .lineHeight(20)
          .padding({
            top: 4,
            bottom: 24
          })
          .width('100%')
      }
      .width('100%')
      .padding({
        left: 20,
        right: 20,
        top: 24,
        bottom: 24
      })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F4F6FB')
  }
}
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐