【HarmonyOS 7 沉浸光感深度实战】 09 常见冲突、性能边界与降级策略
文章目录
前言
沉浸光感放在独立实验页面里时,问题通常比较单纯。组件数量不多,背景也容易控制,某个效果出现异常以后,顺着 ImmersiveMaterial 和几个参数往下检查,通常能够找到原因。
真正进入已有项目以后,情况会复杂很多。一张已经稳定运行的业务卡片,可能同时保留背景色、圆角、阴影和背景模糊;列表里几十个 Item 又复用了同一套组件;页面滚动时还伴随着透明度和位移动画;底部如果继续接入 HDS,设备材质能力和材质等级也会参与最终结果。
这些配置分开使用时都很正常,叠到同一个页面以后,就容易互相影响。我自己前面遇到类似问题时,也会下意识继续调材质参数。效果太淡,就换 ImmersiveStyle;颜色太实,就修改 materialColor;阴影不明显,又开始调整 .shadow()。后来发现,这样排查很容易越调越乱,因为真正的问题有时还停留在普通背景属性这一层。
现在我更习惯先固定一个顺序。先看普通背景和模糊有没有影响材质,再看 materialColor、阴影和自动反色条件。组件本身已经稳定以后,再把注意力放到长列表、动画频率和设备能力上。这样从局部到页面逐层检查,问题会更容易收窄。
性能判断也应该放在后面。一个卡片已经被普通背景覆盖时,继续讨论帧率和设备分档没有太大价值。前面的显示关系处理清楚,后面的性能边界才有意义。
这次实验页面会故意保留三种状态:一张相对干净的推荐组合、一张属性顺序存在干扰的卡片,以及一张使用完全不透明 materialColor 的卡片。页面还会读取当前 MaterialState 和 HDS 材质类型,把属性冲突、设备能力和降级策略放进同一条排查路径。
目前我的测试设备还没有 HarmonyOS 7 实机测试权限,因此当前先通过模拟器核对接口、属性关系和页面结构。帧率、发热、不同算力设备上的材质细节以及真实动画手感,仍然需要在具备权限的真机上继续确认。华为也明确区分模拟器与真机调试环境,部分图形显示和硬件能力存在差异。

一、显示效果出现异常时先排查属性关系
沉浸材质出现异常以后,我现在通常不会马上去换 THIN、REGULAR 或其他样式。更值得先确认的,是当前组件原来已经配置了哪些视觉属性。
沉浸式系统材质本身会参与背景色、边框、阴影以及材质滤镜等显示过程。HarmonyOS 当前的沉浸光感指南也把这些属性纳入材质影响范围,并给出了先完成普通样式设置、随后再调用 systemMaterial 的推荐写法。
所以,看到页面表现不符合预期时,我们可以先按照下面的顺序检查:
普通背景与模糊
↓
沉浸材质参数
↓
前景文字与图标
↓
列表、动画等页面结构
↓
设备能力与降级策略
这个顺序对我比较有用,因为越靠前的问题,通常越容易确认。
背景色已经把材质层盖住时,没有必要继续研究设备等级;materialColor 已经接近完全不透明时,也没有必要继续比较不同 ImmersiveStyle。把这些基础关系整理清楚,后续排查才不会反复绕回来。
普通背景和背景模糊先检查
已有项目接入沉浸材质时,很容易把原来的背景配置一起保留下来。
例如:
Column() {
Text('冲突示例')
}
.width('88%')
.height(108)
.borderRadius(24)
.systemMaterial(this.thinMaterial)
.backgroundColor(Color.White)
这里已经设置了 systemMaterial,后面又继续增加不透明背景色。
在诊断页面中,我会故意保留这种写法,让它和正常组合放在一起比较。不过到了正式项目,通常先把组件恢复到更简单的状态:
Column() {
Text('推荐组合')
}
.width('88%')
.height(108)
.borderRadius(24)
.systemMaterial(this.thinMaterial)
如果原组件里还存在 backgroundBlurStyle、普通边框或其他背景效果,也可以先暂时移除。
当前阶段只需要确认一件事情:系统材质本身能否稳定显示。
材质恢复以后,再把业务真正需要的样式逐项加回来。这样会多操作几次,后面却能清楚知道是哪一个属性开始改变最终结果。官方同样采用先配置尺寸、圆角等属性,随后设置 systemMaterial 的方式。
materialColor 变成纯色块时先看透明度
背景属性没有明显干扰以后,下一个很常见的问题来自 materialColor。
例如:
private readonly opaqueMaterial: uiMaterial.Material =
new uiMaterial.ImmersiveMaterial({
style: uiMaterial.ImmersiveStyle.THIN,
materialColor: '#FFFFFFFF'
});
代码本身能够正常创建材质,画面却可能越来越接近普通白色卡片。
这里的问题来自赋色透明度。
materialColor 会继续参与材质层颜色处理。完全不透明以后,底层背景信息会被大幅压掉,材质原本的通透感也很难继续观察。大家注意,材质赋色需要保留透明度。
页面只需要稍微稳定背景时,可以改成:
private readonly tintedMaterial: uiMaterial.Material =
new uiMaterial.ImmersiveMaterial({
style: uiMaterial.ImmersiveStyle.THIN,
materialColor: '#4DFFFFFF'
});
我自己更习惯从较低的 alpha 开始调。背景仍然可以辨认,同时卡片色调已经趋于统一,这个程度往往已经够用。继续提高不透明度以后,页面虽然更稳定,沉浸材质的空间层次也会随之减弱。
因此,卡片突然接近纯色时,materialColor 往往比 ImmersiveStyle 更值得优先检查。
阴影需要先明确由哪一套规则负责
背景和赋色确认以后,阴影是另一类经常让人绕进去的问题。
ImmersiveOptions 本身提供 applyShadow,默认值为 true。项目中的组件如果又存在自己的 .shadow(),最好明确最终希望保留哪一套视觉策略。
当前诊断页面不需要把阴影问题做得过于复杂。正式项目已经有统一阴影规范时,可以单独准备一份关闭材质阴影的配置,再观察组件原有阴影是否符合设计要求:
private readonly customShadowMaterial:
uiMaterial.Material =
new uiMaterial.ImmersiveMaterial({
style: uiMaterial.ImmersiveStyle.THIN,
applyShadow: false
});
随后仍然由组件设置自己的阴影:
Column() {
Text('自定义阴影')
}
.width('88%')
.height(108)
.borderRadius(24)
.shadow({
radius: 16,
color: '#33000000',
offsetX: 0,
offsetY: 6
})
.systemMaterial(this.customShadowMaterial)
这里真正需要留下的是一条清楚的规则。
项目选择系统材质阴影,就让系统材质负责;项目已经有统一的阴影体系,就在同一设备上确认关闭材质阴影后的实际表现,再决定是否沿用原来的 .shadow()。两套阴影都长期留在页面里,后面调整起来会越来越难解释。
自动反色没有明显变化时继续检查它的前提
普通背景、赋色和阴影都没有问题以后,前景颜色才进入排查范围。
colorInvert 已经打开,文字仍然没有明显变化时,可以继续沿着下面的条件往下检查:
THIN / ULTRA_THIN
↓
前景属性是否位于支持范围
↓
颜色资源是否满足自动反色条件
↓
系统沉浸光感设置是否一致
↓
当前设备是否能够呈现对应效果
这里没有必要继续增加新的文字颜色做随机尝试。
自动反色有自己明确的触发条件,先确认条件会更容易找到原因。沉浸光感会根据设备算力和系统中的光感强度调整最终效果,不同设备上的表现本身也可能存在差异。
前面这几层都确认以后,单个组件已经比较稳定。接下来出现滚动卡顿、动画掉帧或者设备之间差异明显时,才真正进入性能问题。

二、属性关系稳定以后再判断页面的性能边界
单张卡片运行正常,并不代表整个页面也会一直保持同样的状态。
页面进入长列表以后,同时存在的节点数量会增加;加入拖动、滚动显隐和展开动画以后,状态更新频率也会提升;再换到不同设备上,材质本身还会根据设备能力调整表现。
到了这个阶段,排查重点需要从一个组件扩展到整张页面。我通常先看材质到底出现了多少次,随后检查高频动画怎么写,最后再回到真机确认设备差异。这样的顺序比一开始就盯着帧率数字更容易找到真正的优化空间。
长列表里先决定哪些位置真正需要材质
资讯、商品、联系人这类页面很容易出现一个情况:页面整体开始使用沉浸光感以后,每一个 ListItem 也顺手加上材质。视觉上未必因此更清楚,页面里的材质节点却会持续增加。
例如一个几十条数据的列表,可以先尝试这样的结构:
顶部搜索框
→ 沉浸材质
底部操作区域
→ 沉浸材质
普通 ListItem
→ 普通背景
这已经能够形成明确的前后层级。
所以,我现在看长列表时,通常先问一个问题:这块材质需要跟着每一条数据重复出现吗?
没有明确必要时,我会优先把材质留给固定悬浮区域。列表本身的数据量较大时,再使用 LazyForEach 等按需创建方式处理大量 Item。
例如:
List() {
LazyForEach(
this.dataSource,
(item: ItemData) => {
ListItem() {
this.itemBuilder(item)
}
},
(item: ItemData) => item.id
)
}
不过,这里需要把两个问题分开。LazyForEach 处理列表节点创建方式,材质到底需要出现在多少个 Item 上,仍然属于页面设计和性能决策。列表已经按需加载,并不意味着每一个可见 Item 都适合继续叠沉浸材质。
高频动画优先使用图形变换属性
动态页面中的另一个成本来自动画更新。例如悬浮工具栏跟随滚动退出、拖动面板移动、组件淡入淡出,这些状态可能在较短时间里连续变化。
如果高频过程中持续修改布局宽度、高度等属性,页面需要反复参与布局计算。HarmonyOS 当前 Code Linter 已经把使用图形变换替代部分布局属性动画列入推荐性能规则,并明确建议在动效丢帧场景下优先调整。
因此,高频状态可以优先围绕 translate 、opacity、scale 处理。
例如让一块悬浮工具栏退出页面:
this.getUIContext().animateTo({
duration: 180,
curve: Curve.EaseOut
}, () => {
this.toolbarOpacity = 0;
this.toolbarTranslateY = 80;
this.toolbarScale = 0.96;
});
这些变化主要发生在视觉层面,适合滚动显隐这类高频场景。确实需要改变实际布局空间时,宽高变化仍然可以使用。这个时候更值得关注的是发生频率和组件复杂度。
我会简单分成两类:
频繁变化
→ translate / opacity / scale
低频结构变化
→ 根据页面需求调整布局
这种划分不追求统一写法,重点是避免一个高频手势每一帧都触发复杂布局调整。
动态状态单独更新
动态页面还容易出现另一个问题:材质对象跟着手势或者滚动不断创建。
例如下面的逻辑没有必要放进高频回调:
new uiMaterial.ImmersiveMaterial(...)
材质参数没有发生变化时,可以提前准备:
private readonly toolbarMaterial:
uiMaterial.Material =
new uiMaterial.ImmersiveMaterial({
style: uiMaterial.ImmersiveStyle.THIN
});
滚动和动画过程只更新 位置、透明度、缩放、显示状态 材质对象继续复用。
一定要减少频繁创建和销毁对象带来的开销。这里我们把稳定的材质配置和高频的动画状态分开,代码结构也会更容易维护。
性能结论仍然需要回到真机
页面结构已经整理以后,最后才进入真正的性能验证。
模拟器很适合确认 API、页面结构、状态流转和基础视觉结果,却无法替代目标设备上的 GPU、触控、功耗以及设备分档。
大家一定要区分模拟器、真机和预览器的调试差异,并记录了模拟器在图形显示等方面与真机可能存在差别。
因此,我们可以把验证范围分成两部分:
| 模拟器适合确认 | 真机继续确认 |
|---|---|
| API 是否能够调用 | 实际帧率 |
| 页面结构是否正确 | 发热与功耗 |
| 状态切换是否执行 | 动画手感 |
| 材质是否进入基础显示 | 最终材质细节 |
| HDS 查询是否返回结果 | 不同设备能力差异 |
等设备权限具备以后,长列表、动态面板和 HDS 材质都需要重新放到真机环境中测试。

三、降级策略最好在正式接入之前准备完成
属性冲突解决以后,页面结构也经过控制,某些设备或者某些业务场景仍然可能不适合继续保留完整材质。
这种情况很正常。沉浸光感本身会根据设备能力和系统设置调整表现,项目仍然需要负责自己的页面可读性、性能和业务稳定性。
我现在更愿意提前准备三层回退方式:先交给系统自适应,然后缩减页面中的材质和动态效果,最后保留普通背景方案。
第一层先使用系统能够自适应的方案
普通 ArkUI 页面没有特殊要求时,可以从相对克制的材质开始:
private readonly normalMaterial:
uiMaterial.Material =
new uiMaterial.ImmersiveMaterial({
style: uiMaterial.ImmersiveStyle.THIN,
applyShadow: true
});
页面先不要同时加入过重的 materialColor、普通背景模糊和多套动态反馈。
HDS 组件也可以优先保留自适应思路。当前 UI Design Kit 6.1.0(23)已经引入 HDS 材质类型等接口,其中包括 IMMERSIVE。
在已有项目中,我会先让系统承担更多设备适配工作,等页面结构稳定以后,再决定是否有必要手动控制材质等级。
可以简单理解为:
没有特殊设备要求
↓
先采用系统自适应策略
这一步能省掉很多过早的设备分支。
第二层根据 HDS 查询结果收敛策略
确实需要根据设备做判断时,可以读取:
hdsMaterial.getSystemMaterialTypes()
当前诊断页会检查返回结果中是否包含 IMMERSIVE。
如果已经确认当前环境具备对应材质能力,页面继续保留自适应策略;当前环境没有明确确认 IMMERSIVE 时,实验页会提示向更轻量的 SMOOTH 策略收敛。
这里需要把它理解成项目中的保守策略。页面没有必要为了某一张截图中的视觉差异,把框架组件长期固定在高成本等级上。标题栏和底部导航会持续存在,对流畅度和稳定性的要求通常比单次视觉效果更重要。
第三层保留普通背景回退
经过前两层处理以后,仍然可能出现一些页面不适合继续使用材质。长列表已经有明显性能压力,复杂背景始终影响前景阅读,或者正式版本需要覆盖更多设备,而当前真机数据还不够完整,这些情况下都可以回到普通背景。
例如:
Column() {
Text('普通背景回退')
}
.width('88%')
.height(108)
.borderRadius(24)
.backgroundColor('#F2FFFFFF')
我会把这种方案视为正常的工程回退。业务页面首先需要保证文字清楚、操作可用、滚动稳定。沉浸材质用于增强空间层级,它应该建立在这些基本条件已经满足的基础上。
整个降级过程可以按照下面的顺序推进:
系统自适应
↓
减少重复材质节点
↓
减少不必要的动态反馈
↓
根据设备能力收敛 HDS 策略
↓
普通背景回退
每一次只处理当前最明显的问题。
页面材质节点过多,就先减少数量;动态反馈造成压力,就先收掉多余动画;设备能力没有确认,再降低材质要求;这些调整仍然无法保证稳定时,再回到普通背景。这样比重新准备一整套备用页面更容易维护。
实验页面和正式业务页面还要再做一次清理
诊断页面中会出现很多正式产品不需要的内容。
例如:
错误属性组合
MaterialState 状态
HDS 查询结果
降级建议
测试说明
这些内容在定位问题时非常有用,发布到正式业务页面以后却没有必要一直存在。
项目收尾时,可以再检查一遍:
| 实验内容 | 正式页面处理 |
|---|---|
| 冲突对照卡片 | 删除 |
| 调试状态文字 | 删除或转入日志 |
| HDS 查询 | 按设备策略决定是否保留 |
| 普通背景回退 | 保留 |
| 材质参数 | 保留业务需要部分 |
| 真机性能结论 | 进入发布前检查 |
| 实验按钮 | 删除 |
我比较在意这一轮清理。诊断代码长期留在业务组件中,后续维护时很容易分不清某个状态属于正式逻辑还是测试逻辑。实验完成以后及时收掉,页面会清爽很多。
总结
沉浸光感进入已有项目以后,比继续增加参数更重要的,是形成一个稳定的排查顺序。
页面出现异常时,我现在通常先从普通视觉属性开始检查,再进入材质参数和前景颜色。单个组件确认稳定以后,才把问题扩大到长列表、动画和设备能力。
整个过程可以记成:
视觉属性
↓
材质参数
↓
前景颜色
↓
页面结构
↓
设备能力
↓
降级策略
这个顺序能够减少很多无效调整。卡片已经受到不透明背景影响时,继续比较材质档位没有意义;列表本身存在大量节点和高频布局更新时,先去怀疑设备材质等级也很容易偏离真正的问题。
进入性能阶段以后,我更关注材质使用范围和动画更新方式。长列表通过 LazyForEach 等方式控制节点创建,高频变化尽量使用 translate、opacity 和 scale,材质对象则提前创建并保持复用。设备表现仍然不理想时,降级可以继续保持简单。先使用系统自适应,再减少材质节点和动态反馈,随后根据设备能力收敛 HDS 策略,最后保留普通背景回退。
我更看重页面最后是不是稳定。文字能够一直看清,操作响应自然,滚动保持流畅以后,沉浸光感才真正给页面增加了价值。某个页面为了保留材质效果而牺牲这些基本体验时,回退到更轻的方案会更加合适。
当前诊断页面可以在 HarmonyOS 7 模拟器中检查属性冲突、应用状态和 HDS 能力查询。正式用于项目之前,大家仍然需要在具备权限的真机上确认帧率、发热、动画手感以及不同设备能力下的最终材质表现。
完整代码
Main.ets
/**
* HarmonyOS 7 沉浸光感深度实战 09
*
* 验证环境:
* HarmonyOS SDK API 26
* HarmonyOS 7 模拟器
*/
import { uiMaterial } from '@kit.ArkUI';
import { hdsMaterial } from '@kit.UIDesignKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct Main {
@State private materialStateText: string =
'尚未读取';
@State private materialStateColor:
ResourceColor = '#68708A';
@State private hdsTypesText: string =
'尚未查询';
@State private hdsStrategyText: string =
'等待设备能力查询';
@State private supportsImmersive: boolean =
false;
/**
* 推荐组合:
* 使用 THIN 和轻量透明赋色。
* 组件自身不再设置普通背景、模糊和阴影。
*/
private readonly safeMaterial:
uiMaterial.Material =
new uiMaterial.ImmersiveMaterial({
style:
uiMaterial.ImmersiveStyle.THIN,
materialColor:
'#33FFFFFF',
applyShadow:
true
});
/**
* 对照组合:
* materialColor 使用完全不透明的颜色,
* 用于观察背景信息被明显压低后的表现。
*/
private readonly opaqueMaterial:
uiMaterial.Material =
new uiMaterial.ImmersiveMaterial({
style:
uiMaterial.ImmersiveStyle.THIN,
materialColor:
'#FFFFFFFF',
applyShadow:
true
});
aboutToAppear(): void {
this.loadArkUiState();
this.loadHdsCapability();
}
/**
* 读取应用级材质状态。
*/
private loadArkUiState(): void {
const info:
uiMaterial.MaterialInfo =
uiMaterial.getMaterialInfo();
switch (info.state) {
case uiMaterial.MaterialState.DEFAULT:
this.materialStateText =
'DEFAULT';
this.materialStateColor =
'#5065E8';
break;
case uiMaterial.MaterialState.ENABLE:
this.materialStateText =
'ENABLE';
this.materialStateColor =
'#1A8F5D';
break;
case uiMaterial.MaterialState.DISABLE:
this.materialStateText =
'DISABLE';
this.materialStateColor =
'#C85A3A';
break;
default:
this.materialStateText =
`UNKNOWN(${info.state})`;
this.materialStateColor =
'#68708A';
break;
}
}
/**
* 查询 HDS 材质类型,
* 同时生成当前页面使用的降级提示。
*/
private loadHdsCapability(): void {
try {
const types:
Array<hdsMaterial.MaterialType> =
hdsMaterial
.getSystemMaterialTypes();
this.supportsImmersive =
types.indexOf(
hdsMaterial
.MaterialType
.IMMERSIVE
) >= 0;
this.hdsTypesText =
this.getHdsTypeText(types);
this.hdsStrategyText =
this.supportsImmersive
? '保持 ADAPTIVE'
: '收敛到 SMOOTH';
} catch (error) {
const businessError =
error as BusinessError;
this.hdsTypesText =
`查询失败 ${businessError.code} `
+ `${businessError.message}`;
this.supportsImmersive =
false;
this.hdsStrategyText =
'保留普通背景回退';
}
}
/**
* 把 HDS MaterialType 转换成页面文本。
*/
private getHdsTypeText(
types:
Array<hdsMaterial.MaterialType>
): string {
if (types.length === 0) {
return '当前环境未返回材质类型';
}
const names: Array<string> = [];
for (
let index: number = 0;
index < types.length;
index++
) {
const type:
hdsMaterial.MaterialType =
types[index];
switch (type) {
case hdsMaterial.MaterialType.NONE:
names.push('NONE');
break;
case hdsMaterial
.MaterialType
.ADAPTIVE:
names.push('ADAPTIVE');
break;
case hdsMaterial
.MaterialType
.IMMERSIVE:
names.push('IMMERSIVE');
break;
default:
names.push(
`UNKNOWN(${type})`
);
break;
}
}
return names.join('、');
}
@Builder
private sectionTitle(
title: string,
description: string
) {
Column({ space: 4 }) {
Text(title)
.fontSize(21)
.fontWeight(FontWeight.Bold)
.fontColor('#11182C')
.width('100%')
Text(description)
.fontSize(13)
.fontColor('#68708A')
.lineHeight(20)
.width('100%')
}
.width('100%')
.alignItems(
HorizontalAlign.Start
)
}
/**
* 当前环境查询区域。
*/
@Builder
private environmentPanel() {
Column({ space: 10 }) {
Row({ space: 12 }) {
Text('MaterialState')
.width('38%')
.fontSize(13)
.fontColor('#68708A')
Text(this.materialStateText)
.layoutWeight(1)
.fontSize(13)
.fontWeight(
FontWeight.Medium
)
.fontColor(
this.materialStateColor
)
.textAlign(TextAlign.End)
}
.width('100%')
Divider()
.color('#E8EBF2')
Row({ space: 12 }) {
Text('HDS MaterialType')
.width('38%')
.fontSize(13)
.fontColor('#68708A')
Text(this.hdsTypesText)
.layoutWeight(1)
.fontSize(13)
.fontWeight(
FontWeight.Medium
)
.fontColor('#17203A')
.textAlign(TextAlign.End)
.maxLines(3)
}
.width('100%')
Divider()
.color('#E8EBF2')
Row({ space: 12 }) {
Text('HDS 策略')
.width('38%')
.fontSize(13)
.fontColor('#68708A')
Text(this.hdsStrategyText)
.layoutWeight(1)
.fontSize(13)
.fontWeight(
FontWeight.Medium
)
.fontColor(
this.supportsImmersive
? '#1A8F5D'
: '#D06C35'
)
.textAlign(TextAlign.End)
.maxLines(2)
}
.width('100%')
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(20)
}
/**
* 三张对照卡片共用同一块背景。
*/
@Builder
private comparisonBackground() {
Row() {
Column()
.width('34%')
.height('100%')
.backgroundColor('#4B62FF')
Column()
.width('32%')
.height('100%')
.backgroundColor('#59B7FF')
Column()
.layoutWeight(1)
.height('100%')
.backgroundColor('#A266FF')
}
.width('100%')
.height('100%')
}
/**
* 推荐组合。
* 尺寸和圆角设置完成后,再设置系统材质。
*/
@Builder
private safeCard() {
Stack() {
this.comparisonBackground()
Column({ space: 6 }) {
Text('推荐组合')
.fontSize(18)
.fontWeight(
FontWeight.Bold
)
.fontColor('#17203A')
Text(
'透明背景 · 轻量赋色 · systemMaterial 最后'
)
.fontSize(12)
.fontColor('#596179')
.textAlign(TextAlign.Center)
.maxLines(2)
}
.width('88%')
.height(108)
.padding({
left: 10,
right: 10
})
.borderRadius(24)
.justifyContent(
FlexAlign.Center
)
.alignItems(
HorizontalAlign.Center
)
.systemMaterial(
this.safeMaterial
)
}
.width('100%')
.height(160)
.borderRadius(24)
.clip(true)
}
/**
* 属性顺序对照。
*
* 这里故意把不透明背景色放在
* systemMaterial 后面,
* 用于诊断页面观察属性关系。
*/
@Builder
private wrongOrderCard() {
Stack() {
this.comparisonBackground()
Column({ space: 6 }) {
Text('属性顺序冲突')
.fontSize(18)
.fontWeight(
FontWeight.Bold
)
.fontColor('#17203A')
Text(
'systemMaterial 后继续设置不透明背景'
)
.fontSize(12)
.fontColor('#596179')
.textAlign(TextAlign.Center)
.maxLines(2)
}
.width('88%')
.height(108)
.padding({
left: 10,
right: 10
})
.borderRadius(24)
.justifyContent(
FlexAlign.Center
)
.alignItems(
HorizontalAlign.Center
)
.systemMaterial(
this.safeMaterial
)
.backgroundColor(
Color.White
)
}
.width('100%')
.height(160)
.borderRadius(24)
.clip(true)
}
/**
* 完全不透明 materialColor 对照。
*/
@Builder
private opaqueTintCard() {
Stack() {
this.comparisonBackground()
Column({ space: 6 }) {
Text('不透明 materialColor')
.fontSize(18)
.fontWeight(
FontWeight.Bold
)
.fontColor('#17203A')
Text(
'materialColor = #FFFFFFFF'
)
.fontSize(12)
.fontColor('#596179')
.textAlign(TextAlign.Center)
}
.width('88%')
.height(108)
.borderRadius(24)
.justifyContent(
FlexAlign.Center
)
.alignItems(
HorizontalAlign.Center
)
.systemMaterial(
this.opaqueMaterial
)
}
.width('100%')
.height(160)
.borderRadius(24)
.clip(true)
}
/**
* 页面底部保留简短排查顺序。
*/
@Builder
private diagnosticOrder() {
Column({ space: 10 }) {
Text('排查顺序')
.fontSize(16)
.fontWeight(
FontWeight.Bold
)
.fontColor('#17203A')
.width('100%')
Text(
'背景属性 → 材质参数 → 前景颜色 '
+ '→ 页面结构 → 设备能力'
)
.fontSize(13)
.fontColor('#68708A')
.lineHeight(20)
.width('100%')
Text(
'出现性能压力时,先减少重复材质和动态效果,'
+ '再决定 HDS 等级或普通背景回退。'
)
.fontSize(12)
.fontColor('#747C92')
.lineHeight(19)
.width('100%')
}
.width('100%')
.padding(16)
.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(
'当前环境',
'先确认应用状态和 HDS 材质能力。'
)
this.environmentPanel()
this.sectionTitle(
'推荐组合',
'组件只保留必要样式,再设置系统材质。'
)
this.safeCard()
this.sectionTitle(
'冲突示例',
'下面两张卡片保留容易影响材质表现的配置。'
)
this.wrongOrderCard()
this.opaqueTintCard()
this.diagnosticOrder()
Text(
'模拟器用于排查属性和接口,'
+ '性能、发热与设备材质差异仍需真机验证。'
)
.fontSize(12)
.fontColor('#747C92')
.lineHeight(19)
.padding({
top: 4,
bottom: 24
})
.width('100%')
}
.width('100%')
.padding({
left: 20,
right: 20,
top: 24,
bottom: 24
})
}
.width('100%')
.height('100%')
.backgroundColor('#F4F6FB')
}
}
更多推荐




所有评论(0)