沉浸光感
概述
core/spatialization 模块提供 HDS(HarmonyOS Design System)沉浸光感的核心支撑能力,包括窗口信息管理、安全区域监听和沉浸材质工具封装。
HDS 沉浸光感通过为标题栏、底部导航栏等组件应用系统材质,带来通透的毛玻璃质感和流光动效,使界面更加精致沉浸。
模块组成
| 类 / 枚举 | 职责 |
|---|---|
GlobalInfoModel | @ObservedV2 全局设备窗口信息模型 |
WindowUtil | 窗口尺寸与安全区域监听工具 |
MaterialUtil | 沉浸材质工具(API 26+ 完整效果,低版本降级) |
StorageKey | AppStorageV2 共享键名枚举 |
SpatializationConstants | 折叠屏宽高比阈值常量 |
GlobalInfoModel
全局设备信息模型,由 WindowUtil 写入,业务层通过 AppStorageV2.connect 读取。
| 字段 | 类型 | 说明 |
|---|---|---|
statusBarHeight | number | 状态栏高度(vp) |
naviIndicatorHeight | number | 底部导航指示器高度(vp) |
deviceWidth / deviceHeight | number | 窗口尺寸(vp) |
widthBreakpoint | WidthBreakpoint | 宽度断点 |
heightBreakpoint | HeightBreakpoint | 高度断点 |
needDynamicHideBar | boolean | 是否需要动态隐藏底部栏(折叠屏横屏场景) |
typescript
import { AppStorageV2 } from '@kit.ArkUI';
import { GlobalInfoModel, StorageKey } from '@core/spatialization';
@Local globalInfo: GlobalInfoModel =
AppStorageV2.connect(GlobalInfoModel, StorageKey.GLOBAL_INFO) ?? new GlobalInfoModel();
// 使用示例
const bottomMargin = this.globalInfo.naviIndicatorHeight > 0
? this.globalInfo.naviIndicatorHeight
: 16;WindowUtil
在 EntryAbility.onWindowStageCreate 加载页面后调用一次,自动监听窗口尺寸和安全区变化。
框架已在 EntryAbility 中接入,无需重复调用。
typescript
// EntryAbility.ets(框架已配置)
windowStage.loadContent('view/EntryPage', (_) => {
WindowUtil.initialize(windowStage);
});MaterialUtil
封装通用组件的沉浸材质应用逻辑。HDS 系列组件(HdsNavigation、HdsTabs)通过 systemMaterialEffect 属性直接支持沉浸效果,无需 MaterialUtil。
MaterialUtil 主要用于 菜单、弹窗等非 HDS 组件 的材质注入。
getMaterialOptions
为 bindMenu、promptAction.openMenu 等的 Options 对象注入材质(API 26+ 生效,低版本原样返回)。
typescript
import { MaterialUtil } from '@core/spatialization';
promptAction.openMenu(
contentNode,
{ id: menuId },
MaterialUtil.getMaterialOptions<MenuOptions>(
{ mask: false, backgroundBlurStyle: BlurStyle.COMPONENT_THICK }
) as MenuOptions,
);getMaterialModifier
为通用组件 CommonModifier 应用材质(API 26+ 使用 ImmersiveMaterial,低版本使用 backgroundBlurStyle 降级)。
typescript
import { MaterialUtil, MaterialModifierOptions } from '@core/spatialization';
const modifier = MaterialUtil.getMaterialModifier({
modifier: new CommonModifier(),
backgroundColor: $r('sys.color.comp_background_tertiary'),
backgroundBlurStyle: BlurStyle.COMPONENT_THICK,
});
Button('操作')
.attributeModifier(modifier)沉浸光感接入示例
HdsNavigation 标题栏
typescript
import { hdsMaterial, HdsNavigation, HideMode, ScrollEffectType } from '@kit.UIDesignKit';
import { GlobalInfoModel, StorageKey } from '@core/spatialization';
@Local globalInfo: GlobalInfoModel =
AppStorageV2.connect(GlobalInfoModel, StorageKey.GLOBAL_INFO) ?? new GlobalInfoModel();
private scroller: Scroller = new Scroller();
HdsNavigation() {
// 页面内容
}
.titleBar({
style: {
scrollEffectOpts: {
enableScrollEffect: true,
scrollEffectType: ScrollEffectType.GRADIENT_BLUR,
},
systemMaterialEffect: {
materialType: hdsMaterial.MaterialType.ADAPTIVE,
materialLevel: hdsMaterial.MaterialLevel.ADAPTIVE,
},
},
avoidLayoutSafeArea: true,
enableComponentSafeArea: false,
})
.dynamicHideTitleBar({
hideTitleArea: true,
hideStatusBar: true,
mode: HideMode.SCROLL_UP_TO,
})
.bindToScrollable([this.scroller])
.ignoreLayoutSafeArea([LayoutSafeAreaType.SYSTEM], [LayoutSafeAreaEdge.TOP, LayoutSafeAreaEdge.BOTTOM])HdsTabs 悬浮底部导航
typescript
import { hdsMaterial, HdsTabs } from '@kit.UIDesignKit';
import { GlobalInfoModel, StorageKey } from '@core/spatialization';
@Local globalInfo: GlobalInfoModel =
AppStorageV2.connect(GlobalInfoModel, StorageKey.GLOBAL_INFO) ?? new GlobalInfoModel();
HdsTabs() {
// TabContent
}
.barOverlap(true)
.barPosition(BarPosition.End)
.barFloatingStyle({
barBottomMargin: this.globalInfo.naviIndicatorHeight > 0
? this.globalInfo.naviIndicatorHeight
: $r('sys.float.padding_level8'),
adaptToHandedness: true,
systemMaterialEffect: {
materialType: hdsMaterial.MaterialType.ADAPTIVE,
materialLevel: hdsMaterial.MaterialLevel.ADAPTIVE,
},
})注意事项
- 应用级开关:框架已在
entry/module.json5配置ohos.arkui.UIMaterial.state: enable,全局开启沉浸材质。 - API 兼容:
HdsNavigation、HdsTabs的systemMaterialEffect在 API 23 即可使用。systemMaterial()通用属性需 API 26,框架内部已做检测降级。 - 内容区偏移:使用
ignoreLayoutSafeArea全屏布局时,List/Scroll 等内容容器需通过contentStartOffset预留状态栏 + 标题栏的高度,避免内容被遮挡。
演示包
packages/spatialization 提供两个可运行的演示场景,在应用 扩展 Tab 中可直接进入:
| 入口 | 场景 |
|---|---|
| 首眼沉浸光感 | HdsNavDestination + HdsTabs,标题栏渐变模糊 + 底部悬浮导航 |
| 自适应悬浮导航 | HdsTabs MiniBar 折叠展开,多 Tab scroller 绑定联动 |