HarmonyOS 多设备短视频开发 : 06 — 窗口管理实战:沉浸式布局与避让区域处理

HarmonyOS 多设备短视频开发 : 06 — 窗口管理实战:沉浸式布局与避让区域处理 06 — 窗口管理实战沉浸式布局与避让区域处理一、引言多设备应用需要精确管理窗口状态包括尺寸变化、避让区域状态栏、导航栏、挖孔屏、手势区、键盘和全屏切换。本文以WindowUtil工具类为核心分析 HarmonyOS 窗口管理的最佳实践。二、WindowUtil 单例设计采用单例模式全局唯一的窗口管理器export class WindowUtil { private static instance: WindowUtil | undefined undefined; static getInstance(): WindowUtil { if (!WindowUtil.instance) { WindowUtil.instance new WindowUtil(); } return WindowUtil.instance; } }三、WindowInfo 状态模型使用ObservedV2和Trace装饰器使窗口状态变化可被 UI 响应式监听ObservedV2 export class WindowInfo { Trace public windowStatusType: window.WindowStatusType; Trace public isFullScreen: boolean; Trace public orientation: window.Orientation; Trace public windowSize: window.Size; Trace public widthBp: WidthBreakpoint; Trace public heightBp: HeightBreakpoint; Trace public avoidSystem?: window.AvoidArea; // 状态栏 Trace public avoidNavigationIndicator?: window.AvoidArea; // 导航栏 Trace public avoidCutout?: window.AvoidArea; // 挖孔区 Trace public avoidSystemGesture?: window.AvoidArea; // 手势区 Trace public avoidKeyboard?: window.AvoidArea; // 键盘区 Trace public statusBarTopVp: number; Trace public navigationBarBottomVp: number; }四、窗口监听注册4.1 初始化流程在updateWindowInfo()中完成一次性初始化和监听注册updateWindowInfo(): void { // 1. 窗口状态 this.mainWindowInfo.windowStatusType this.mainWindow.getWindowStatus(); this.mainWindow.on(windowStatusChange, this.onStatusTypeChange); // 2. 窗口尺寸 断点 this.mainWindowInfo.windowSize { width, height }; this.mainWindowInfo.widthBp this.uiContext.getWindowWidthBreakpoint(); this.mainWindow.on(windowSizeChange, this.onWindowSizeChange); // 3. 避让区域 this.mainWindowInfo.avoidSystem this.mainWindow.getWindowAvoidArea(TYPE_SYSTEM); this.mainWindow.on(avoidAreaChange, this.onAvoidAreaChange); this.syncWindowInsetsVp(); }4.2 避让区域监听五种避让区域分别监听public onAvoidAreaChange (avoidOptions: window.AvoidAreaOptions) { switch (avoidOptions.type) { case AvoidAreaType.TYPE_SYSTEM: // 状态栏 case AvoidAreaType.TYPE_CUTOUT: // 挖孔屏 case AvoidAreaType.TYPE_SYSTEM_GESTURE: // 边缘手势 case AvoidAreaType.TYPE_KEYBOARD: // 键盘 case AvoidAreaType.TYPE_NAVIGATION_INDICATOR: // 导航指示器 } this.syncWindowInsetsVp(); // 同步 vp 值 };五、全屏沉浸式设置5.1 设置全屏布局setFullScreen(isFullScreen: boolean): void { this.mainWindow.setWindowLayoutFullScreen(isFullScreen) .then(() { this.mainWindowInfo.isFullScreen isFullScreen; }); }5.2 设置系统栏属性setWindowSystemBarProperties(props: window.SystemBarProperties): void { this.mainWindow.setWindowSystemBarProperties(props); }5.3 设置窗口方向setWindowOrientation(orientation: window.Orientation): void { this.mainWindow.setPreferredOrientation(orientation); }六、沉浸式视频播放中的应用在自适应沉浸式算法中statusBarTopVp和navigationBarBottomVp用于计算视频的可视区域// ImmersionRules.ets 中计算可用区域 const restShowAreaHeight windowHeight - bottomTabHeight - statusBarHeight; const restShowAreaWidth windowWidth;七、资源释放页面销毁时取消监听防止内存泄漏release(): void { this.mainWindow.off(windowStatusChange); this.mainWindow.off(windowSizeChange); this.mainWindow.off(avoidAreaChange); }八、最佳实践单例模式全局共享一个窗口管理器避免重复监听ObservedV2 Trace窗口状态变化自动驱动 UI 更新AppStorageV2 持久化WindowInfo通过AppStorageV2.connect跨页面共享px2vp 转换避让区域返回 px 单位需要使用ctx.px2vp()转换为 vp异常处理所有窗口 API 调用都需要 try-catch 处理防止异常崩溃