先查询能力,再观察具体控件
材质实验页在 API 26 模拟器上运行真实uiMaterial接口。当前镜像返回supported=true、level=0;配套 SDK 中 0 对应EXQUISITE。这是当前镜像的查询结果,不将它外推为所有模拟器或设备的材质等级。
this.support=`supported=${uiMaterial.isImmersiveMaterialSupported()}level=${uiMaterial.getGlobalMaterialLevel()}`;页面选择 Slider 和 Switch 类型的 Toggle,因为官方明确这两类组件的沉浸光感可在全页面生效。普通内容区域不能随意套用只允许标题栏或底部 TabBar 生效的其他组件规则。工程 targetSDKVersion 已设为 26.0.0,实验采用组件级配置,没有额外修改应用的全局材质开关。
privatematerial:uiMaterial.Material=newuiMaterial.ImmersiveMaterial({style:uiMaterial.ImmersiveStyle.REGULAR});Slider 的systemMaterial根据页面状态选择这个材质或uiMaterial.Material.empty。Toggle 同时控制自身和 Slider 的材质请求。材质开启状态由@State materialOn直接驱动,因此点击后提示和属性一起更新。不要把状态变量命名为enabled,它会与 ArkUI 组件已有方法冲突;示例使用 materialOn 表达独立的材质状态。
关闭效果要使用 empty
undefined表示恢复默认效果,uiMaterial.Material.empty才是显式关闭。对于默认就开启材质的组件,二者会产生不同结果,不能用“清空参数”代替关闭。
.systemMaterial(this.materialOn?this.material:uiMaterial.Material.empty)当前 Demo 可切换浅色和深色背景,显示正在请求材质还是已显式关闭。模拟器已走通查询、开启、关闭与背景切换路径,截图记录相同控件的实际页面。这里使用纯色背景,尚不足以证明复杂图片后的折射、模糊和运动效果质量;纹理背景、更多弹窗组件与功耗仍属于后续扩展。
将最小实测扩展到展厅
展品大图作为背景时,工具栏既要融入画面,又要让暂停、返回和收藏保持清楚。单纯降低背景透明度容易在某些图片上看不清文字,而每个组件都加厚重底色又会遮挡内容。
详情工具栏、注释弹窗与操作菜单应分别选择材质和层级,再结合真实背景检查可读性。API 26 的具体组件支持和等级以配套指南为准,手写模糊背景不能作为系统材质能力的验收结果。
先分清内容层与操作层
展品画面是内容层,工具栏是持续操作层,弹出的注释是临时阅读层。层级关系明确后,再决定哪些区域需要透出背景,哪些区域必须提供稳定的阅读底色。
材质效果不能代替信息层级。主操作仍需要合适的文字、间距和状态反馈;如果所有按钮都发亮,用户反而难以找到当前最重要的动作。
能力选择放在统一适配层
不同设备、系统版本和组件可能支持不同效果。应用可以维护自己的材质意图,由适配层根据真实能力选择系统实现,并提供可读的基础样式。
typeSurfaceRole='toolbar'|'annotation'|'menu';interfaceSurfaceIntent{role:SurfaceRole;textPriority:'normal'|'high';allowBackgroundDetail:boolean;}这里没有定义系统材质枚举,避免让业务代码依赖未经核实的名字。接入时再将 SurfaceIntent 映射到当前 SDK 的正式参数,并记录支持与回退条件。
用极端背景检查文字
选择全亮、全暗、高频纹理和强色块四组背景,在同一组件上检查文字与图标。默认示例图看起来漂亮,并不能代表换成用户自己的照片后仍可读。
注释长文更适合稳定阅读底层;短工具栏可以允许更多背景参与。交互时如果材质动态变化,也要保证文字不在过渡过程中消失或跳动。
弹窗和菜单保留明确边界
弹窗覆盖 3D 场景时,需要明确焦点、关闭方式和背景是否继续响应。若背景仍可旋转,用户滚动注释可能误触模型。材质只负责视觉,输入与焦点由页面交互合同管理。
打开注释 → 暂停背景手势 → 显示阅读层并设置焦点 关闭注释 → 恢复原入口焦点 → 恢复背景交互大字体或窄窗口下,弹窗内容需要滚动和安全区域处理,不能用缩小字体来勉强维持设计图比例。
回退样式也属于设计结果
设备不支持目标效果时,使用明确的实色或基础表面样式,保持同样的操作顺序与信息层级。回退不应突然改变按钮位置,也不应隐藏关键动作。
测试报告分别展示支持与回退分支。系统能力检测失败时记录原因,不默认返回支持;但用户界面仍应可以完成阅读与返回。
视觉效果与渲染成本一起观察
多个动态材质叠加在 3D 场景上,可能增加渲染开销。固定相机路径和交互动作,比较开启前后的帧时间与页面响应。测量时保持模型、背景和屏幕条件一致,不把素材差异算成材质成本。
当前 Demo 包含 Slider、Toggle、明暗背景切换和能力信息。向展厅扩展时,可另建工具栏、注释弹窗与菜单样例,分别完成可读性、焦点和性能对照,再推广到其他页面。
工具栏与阅读层采用不同决策
| 表面 | 初始选择 | 触发回退的条件 |
|---|---|---|
| 短工具栏 | 能力允许时使用目标系统材质 | 背景干扰文字,或能力不可用 |
| 长注释 | 稳定阅读底色优先 | 大字体下调整尺寸与滚动,不降低字号 |
| 操作菜单 | 明确边界及焦点 | 不因背景效果削弱选中与禁用状态 |
全局套用同一种材质便于统一外观,却会把阅读层和短操作层的矛盾一起带入;按角色映射多一层配置,但更容易稳定回退。先完成三种基础表面和焦点恢复,再核对系统材质入口,最后用固定 3D 路线比较开销。支持检测、视觉可读和任务可完成是三项独立验收,不合并成一个“效果开启成功”。
参考:沉浸光感官方课程入口、HarmonyOS 7 新能力。
接入依据:开启沉浸光感、组件适配沉浸光感。
材质开关和背景状态如何直接驱动控件
控件绑定 materialOn,关闭时显式使用 Material.empty。背景与各正文 Text 的 fontColor 使用同一 dark 状态,按钮独立使用白色文字。支持探测失败时仍展示错误信息与基础控件,不能以查询值代替真实材质效果检查。
import{uiMaterial}from'@kit.ArkUI';import{LabTheme}from'../common/LabTheme';@Entry@Componentstruct MaterialLabPage{@StatematerialOn:boolean=false;@Statecapable:boolean=false;@Statedark:boolean=false;@Statevalue:number=40;@Statesupport:string='等待查询';privatematerial:uiMaterial.Material=newuiMaterial.ImmersiveMaterial({style:uiMaterial.ImmersiveStyle.REGULAR});aboutToAppear():void{try{this.capable=uiMaterial.isImmersiveMaterialSupported();this.materialOn=this.capable;constlevel:number=uiMaterial.getGlobalMaterialLevel();this.support=`supported=${this.capable}level=${level}`;}catch(error){this.capable=false;this.materialOn=false;this.support=(errorasError).message;}}build(){Column({space:22}){Text('24 · 组件沉浸光感').fontSize(26).fontWeight(FontWeight.Bold).fontColor(this.dark?Color.White:LabTheme.ink)Text(this.support).fontSize(16).id('materialSupport').fontColor(this.dark?Color.White:LabTheme.ink)Text('展厅音量').fontSize(20).fontColor(this.dark?Color.White:LabTheme.ink)Slider({value:this.value,min:0,max:100,step:1}).systemMaterial(this.materialOn?this.material:uiMaterial.Material.empty).onChange((value:number)=>{this.value=value;})Text(`音量${this.value}`).fontSize(18).fontColor(this.dark?Color.White:LabTheme.ink)Toggle({type:ToggleType.Switch,isOn:this.materialOn}).systemMaterial(this.materialOn?this.material:uiMaterial.Material.empty).enabled(this.capable).onChange((value:boolean)=>{this.materialOn=this.capable&&value;})Text(this.materialOn?'已请求系统材质':'已显式关闭材质').fontSize(18).fontColor(this.dark?Color.White:LabTheme.ink)Button('切换明暗背景').fontColor(Color.White).id('materialBackground').onClick(()=>{this.dark=!this.dark;})Text('比较相同控件在两种背景下的可读性。实际材质等级由设备决定。').fontSize(16).fontColor(this.dark?Color.White:LabTheme.ink)Blank()Button('返回目录').fontColor(Color.White).onClick(()=>{this.getUIContext().getRouter().back();})}.padding(28).width('100%').height('100%').backgroundColor(this.dark?LabTheme.ink:LabTheme.background)}}exportclassLabTheme{staticreadonlybackground:string='#F4F1EA';staticreadonlyink:string='#16324B';staticreadonlyaccent:string='#276E70';staticreadonlycard:string='#FFFFFF';staticreadonlymuted:string='#536677';}| 操作或边界 | 应检查的结果 |
|---|---|
| 关闭材质 | Slider 和 Toggle 同时使用 empty |
| 切换背景 | 文字与背景成对切换 |
| 能力查询失败 | 展示错误,基础交互仍保留 |
能力探测返回 false 或抛出异常时,materialOn 与 capable 同时归零,开关禁用;两个控件直接绑定 Material.empty。探测成功后才允许用户启用系统材质。
真机能力值、明暗与开关对照
2026-09-20,HBN-AL80(API 26)回读 supported=true、level=1,页面开关为开启,显示“已请求系统材质”,Slider 值为 40。该设备等级与前述模拟器的 level=0 不同,适配层应使用实际查询值。
旧实现将 foregroundColor 放在根 Column 上,浅色状态下蓝按钮也显示深色文字。修订后移除父层前景色,将 dark 对应的颜色直接绑定到正文 Text,按钮继续显式设置白字。真机四种组合均完成操作与回读:
| 背景 | 材质开关 | 页面提示 |
|---|---|---|
| 浅色 | 开 | 已请求系统材质 |
| 深色 | 开 | 已请求系统材质 |
| 深色 | 关 | 已显式关闭材质 |
| 浅色 | 关 | 已显式关闭材质 |
四组截图与开关状态分别核对,材质能力值均为 supported=true、level=1。纯色静态背景的切换覆盖基础交互与文字显示;复杂纹理下的折射、运动效果和渲染成本仍需专门场景测量。