Skip to content

沉浸光感

概述

core/spatialization 模块提供 HDS(HarmonyOS Design System)沉浸光感的核心支撑能力,包括窗口信息管理、安全区域监听和沉浸材质工具封装。

HDS 沉浸光感通过为标题栏、底部导航栏等组件应用系统材质,带来通透的毛玻璃质感和流光动效,使界面更加精致沉浸。

模块组成

类 / 枚举职责
GlobalInfoModel@ObservedV2 全局设备窗口信息模型
WindowUtil窗口尺寸与安全区域监听工具
MaterialUtil沉浸材质工具(API 26+ 完整效果,低版本降级)
StorageKeyAppStorageV2 共享键名枚举
SpatializationConstants折叠屏宽高比阈值常量

GlobalInfoModel

全局设备信息模型,由 WindowUtil 写入,业务层通过 AppStorageV2.connect 读取。

字段类型说明
statusBarHeightnumber状态栏高度(vp)
naviIndicatorHeightnumber底部导航指示器高度(vp)
deviceWidth / deviceHeightnumber窗口尺寸(vp)
widthBreakpointWidthBreakpoint宽度断点
heightBreakpointHeightBreakpoint高度断点
needDynamicHideBarboolean是否需要动态隐藏底部栏(折叠屏横屏场景)
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 系列组件(HdsNavigationHdsTabs)通过 systemMaterialEffect 属性直接支持沉浸效果,无需 MaterialUtil

MaterialUtil 主要用于 菜单、弹窗等非 HDS 组件 的材质注入。

getMaterialOptions

bindMenupromptAction.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 兼容HdsNavigationHdsTabssystemMaterialEffect 在 API 23 即可使用。systemMaterial() 通用属性需 API 26,框架内部已做检测降级。
  • 内容区偏移:使用 ignoreLayoutSafeArea 全屏布局时,List/Scroll 等内容容器需通过 contentStartOffset 预留状态栏 + 标题栏的高度,避免内容被遮挡。

演示包

packages/spatialization 提供两个可运行的演示场景,在应用 扩展 Tab 中可直接进入:

入口场景
首眼沉浸光感HdsNavDestination + HdsTabs,标题栏渐变模糊 + 底部悬浮导航
自适应悬浮导航HdsTabs MiniBar 折叠展开,多 Tab scroller 绑定联动