小雨同学 2026-09-06 10:39:27 发布前言
沉浸光感放在独立实验页面里时,问题通常比较单纯。组件数量不多,背景也容易控制,某个效果出现异常以后,顺着 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@Componentstruct 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') }}暂无评论数据
发布
小雨同学
产品总监、独立开发者社群主理人、资深全栈工程师,HarmonyOS应用开发者高级认证,PMP认证,CSDN博客专家,鸿蒙极客,Trae Fellow,阿里云社区专家博主、51CTO 博客专家、OpenTiny 优秀布道师、科大讯飞荣誉讲师。
帖子
提问
粉丝
【HarmonyOS 7 沉浸光感深度实战】10 通用组件封装与现有项目接入
2026-09-08 09:49:50 发布【HarmonyOS 7 沉浸光感深度实战】 09 常见冲突、性能边界与降级策略
2026-09-06 10:39:27 发布
0
京公网安备:11010502051901号