《悬浮窗效果》二、Interface_WindowStage使用指南

HarmonyOS Interface (WindowStage) 使用指南:从入门到实战

摘要:WindowStage是 HarmonyOS 应用窗口管理的核心调度者,负责管理应用的生命周期、页面加载和多窗口协调。本文基于 HarmonyOS NEXT开发实践,系统讲解WindowStage接口的核心方法、生命周期回调和完整示例代码,帮助开发者掌握应用窗口阶段的控制能力。


效果

一、WindowStage 接口概述

WindowStage代表应用的窗口阶段,是 UIAbility 与窗口系统之间的桥梁。每个 UIAbility 在onWindowStageCreate回调中接收一个WindowStage实例,通过它可以:

  • 加载应用页面内容
  • 获取主窗口实例
  • 创建应用子窗口
  • 监听窗口事件
  • 管理窗口布局与全屏模式

1.1 导入方式

import{window}from'@kit.ArkUI';

1.2 获取 WindowStage 实例

WindowStage实例由系统在 UIAbility 生命周期中自动创建并传入,开发者无需手动创建:

exportdefaultclassEntryAbilityextendsUIAbility{onWindowStageCreate(windowStage:window.WindowStage):void{// 此处获取 windowStage 实例}}

二、生命周期回调

2.1 onWindowStageCreate

当应用窗口阶段创建时触发,是初始化窗口和加载页面的关键入口

onWindowStageCreate(windowStage:window.WindowStage):void{hilog.info(0x0000,'app','窗口阶段已创建');// 1. 加载主页面windowStage.loadContent('pages/Index',(err)=>{if(err.code){hilog.error(0x0000,'app','加载失败: %{public}s',JSON.stringify(err));return;}hilog.info(0x0000,'app','页面加载成功');});}

2.2 onWindowStageDestroy

当应用窗口阶段销毁时触发,用于释放窗口相关资源。

onWindowStageDestroy():void{hilog.info(0x0000,'app','窗口阶段已销毁');// 清理资源}

2.3 完整生命周期流程

UIAbility.onCreate() ↓ UIAbility.onWindowStageCreate(windowStage) ← 窗口阶段创建 ↓ windowStage.loadContent('pages/Index') ← 加载页面 ↓ 页面 aboutToAppear() → build() ← 页面渲染 ↓ UIAbility.onForeground() ← 应用进入前台 ↓ UIAbility.onBackground() ← 应用进入后台 ↓ UIAbility.onWindowStageDestroy() ← 窗口阶段销毁 ↓ UIAbility.onDestroy() ← Ability销毁

三、核心方法详解

3.1 loadContent(path, callback)

加载应用主页面内容,是onWindowStageCreate中最核心的调用。

windowStage.loadContent('pages/Index',(err)=>{if(err.code){hilog.error(0x0000,'app','加载失败: %{public}s',JSON.stringify(err));return;}// 页面加载成功后的初始化操作});

参数说明:

  • path:页面路由地址,对应main_pages.json中配置的页面路径
  • callback:加载完成回调,err.code为 0 表示成功

重要提示:loadContent必须在getMainWindowSync()等方法之前调用,或者在其回调中执行后续操作。

3.2 getMainWindowSync()

同步获取应用主窗口实例。

letmainWindow:window.Window=windowStage.getMainWindowSync();

获取主窗口后,可以进行以下操作:

// 获取UI上下文letuiContext=mainWindow.getUIContext();// 获取窗口属性letprops=mainWindow.getWindowProperties();letwindowId=props.id;// 设置全屏mainWindow.setWindowLayoutFullScreen(true);// 获取避让区域letavoidArea=mainWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);

3.3 createSubWindow(name, callback)

在当前窗口阶段创建应用子窗口。

windowStage.createSubWindow('mySubWindow',(err,subWindow)=>{if(err.code){hilog.error(0x0000,'app','创建子窗口失败: %{public}s',err.message);return;}// 子窗口创建成功,进行配置subWindow.setUIContent('subwindow/SubPage',()=>{subWindow.setWindowBackgroundColor('#00000000');});subWindow.moveWindowTo(0,300);subWindow.resize(200,200);subWindow.showWindow();});

参数说明:

  • name:子窗口名称,用于后续通过window.findWindow(name)查找
  • callback:创建回调,返回(err, subWindow)两个参数

注意事项:

  • 子窗口名称必须唯一
  • 子窗口默认不可见,需调用showWindow()显示
  • 子窗口需要通过setUIContent设置加载页面

3.4 getMainWindow()

异步获取主窗口(推荐使用getMainWindowSync替代)。

windowStage.getMainWindow((err,mainWindow)=>{if(!err.code){// 使用主窗口}});

3.5 getLastWindow(callback)

获取当前应用内最上层的子窗口。

windowStage.getLastWindow((err,topWindow)=>{if(!err.code){hilog.info(0x0000,'app',`最上层窗口ID:${topWindow.getWindowProperties().id}`);}});

3.6 setWindowLayoutFullScreen

通过 WindowStage 设置全屏布局(与通过 Window 设置效果一致)。

// 推荐在 loadContent 回调中通过主窗口设置letmainWindow=windowStage.getMainWindowSync();mainWindow.setWindowLayoutFullScreen(true);

四、完整示例:WindowStage 综合应用

以下示例展示如何在onWindowStageCreate中完成窗口初始化、全屏设置、避让区域获取、全局上下文存储等操作。

4.1 EntryAbility 完整实现

import{AbilityConstant,ConfigurationConstant,UIAbility,Want}from'@kit.AbilityKit';import{hilog}from'@kit.PerformanceAnalysisKit';import{window}from'@kit.ArkUI';constDOMAIN=0x0000;exportdefaultclassEntryAbilityextendsUIAbility{onCreate(want:Want,launchParam:AbilityConstant.LaunchParam):void{hilog.info(DOMAIN,'app','Ability onCreate');}onDestroy():void{hilog.info(DOMAIN,'app','Ability onDestroy');}onWindowStageCreate(windowStage:window.WindowStage):void{hilog.info(DOMAIN,'app','onWindowStageCreate');// Step 1: 加载主页面windowStage.loadContent('pages/Index',(err)=>{if(err.code){hilog.error(DOMAIN,'app','加载失败: %{public}s',JSON.stringify(err));return;}hilog.info(DOMAIN,'app','页面加载成功');// Step 2: 获取UI上下文并存储到AppStorageletmainWindow=windowStage.getMainWindowSync();letuiContext=mainWindow.getUIContext();AppStorage.setOrCreate('uiContext',uiContext);// Step 3: 存储windowStage供页面使用AppStorage.setOrCreate('windowStage',windowStage);// Step 4: 存储主窗口IDAppStorage.setOrCreate('mainWindowId',mainWindow.getWindowProperties().id);// Step 5: 设置全屏布局mainWindow.setWindowLayoutFullScreen(true);// Step 6: 获取状态栏避让区域letsysAvoidArea=mainWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);lettopRectHeight=sysAvoidArea.topRect.height;AppStorage.setOrCreate('topRectHeight',topRectHeight);// Step 7: 获取导航条避让区域letnavAvoidArea=mainWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);letbottomRectHeight=navAvoidArea.bottomRect.height;AppStorage.setOrCreate('bottomRectHeight',bottomRectHeight);});}onWindowStageDestroy():void{hilog.info(DOMAIN,'app','onWindowStageDestroy');}onForeground():void{hilog.info(DOMAIN,'app','onForeground');}onBackground():void{hilog.info(DOMAIN,'app','onBackground');}}

4.2 页面中使用 WindowStage 创建子窗口(状态管理V2版本)

import{window}from'@kit.ArkUI';import{hilog}from'@kit.PerformanceAnalysisKit';@Entry@ComponentV2struct Index{@LocalwindowStage:window.WindowStage=AppStorage.get('windowStage')aswindow.WindowStage;@LocalisSubWindowCreated:boolean=false;// 创建子窗口createSubWindow():void{if(this.isSubWindowCreated){hilog.info(0x0000,'app','子窗口已创建');return;}this.windowStage.createSubWindow('demoSubWin',(err,subWin)=>{if(err.code){hilog.error(0x0000,'app','创建失败: %{public}s',err.message);return;}// 设置子窗口页面subWin.setUIContent('subwindow/SubPage',()=>{subWin.setWindowBackgroundColor('#00000000');});// 设置位置和大小letuiContext=this.windowStage.getMainWindowSync().getUIContext();subWin.moveWindowTo(0,300);subWin.resize(uiContext.vp2px(60),uiContext.vp2px(60));// 显示子窗口subWin.showWindow();this.isSubWindowCreated=true;});}// 销毁子窗口asyncdestroySubWindow():Promise<void>{try{letsubWin=window.findWindow('demoSubWin');awaitsubWin.destroyWindow();this.isSubWindowCreated=false;}catch(err){hilog.error(0x0000,'app','销毁失败: %{public}s',JSON.stringify(err));}}build(){Column({space:20}){Text('WindowStage 示例').fontSize(24).fontWeight(FontWeight.Bold)Button(this.isSubWindowCreated?'销毁子窗口':'创建子窗口').onClick(()=>{if(this.isSubWindowCreated){this.destroySubWindow();}else{this.createSubWindow();}})}.width('100%').height('100%').justifyContent(FlexAlign.Center)}}

五、WindowStage 与多窗口协调

5.1 窗口焦点管理

在多窗口场景下,需要管理窗口焦点的切换:

// 将焦点从子窗口转移回主窗口setTimeout(()=>{letsubId=window.findWindow('subWin').getWindowProperties().id;letmainId=windowStage.getMainWindowSync().getWindowProperties().id;window.shiftAppWindowFocus(subId,mainId);},500);

5.2 EventHub 事件通信

通过eventHub实现 Ability 与页面之间的事件通信:

// EntryAbility 中发送事件onForeground():void{this.context.eventHub.emit('onForeground');}// 页面中监听事件aboutToAppear():void{letctx=this.getUIContext().getHostContext();ctx?.eventHub.on('onForeground',()=>{// 应用回到前台时的处理逻辑});}aboutToDisappear():void{letctx=this.getUIContext().getHostContext();ctx?.eventHub.off('onForeground');}

5.3 通过 AppStorage 实现全局数据共享

WindowStage相关的全局数据推荐通过AppStorage管理:

// 存储AppStorage.setOrCreate('windowStage',windowStage);AppStorage.setOrCreate('uiContext',uiContext);AppStorage.setOrCreate('topRectHeight',topRectHeight);AppStorage.setOrCreate('bottomRectHeight',bottomRectHeight);// 页面中读取@StorageLink('windowStage')windowStage:window.WindowStage;@StorageProp('topRectHeight')topRectHeight:number=0;

六、开发要点与最佳实践

6.1 loadContent 回调中的初始化顺序

loadContent 回调 ├── 1. 获取 UIContext 并存储 ├── 2. 存储 WindowStage ├── 3. 设置全屏布局 ├── 4. 获取避让区域高度 └── 5. 其他初始化操作

顺序很重要:必须先loadContent成功,再获取主窗口进行后续设置。

6.2 子窗口页面路由配置

子窗口页面需要在main_pages.json中注册:

{"src":["pages/Index","subwindow/SubPage"]}

6.3 避免重复创建子窗口

// 创建前检查是否已存在try{letexisting=window.findWindow('subWinName');// 已存在,直接显示existing.showWindow();}catch(err){// 不存在,创建新窗口windowStage.createSubWindow('subWinName',callback);}

6.4 应用退出时清理子窗口

onBackground():void{// 应用进入后台时,可选择隐藏或销毁子窗口try{letsubWin=window.findWindow('subWinName');subWin.hideWindow();}catch(err){// 子窗口不存在}}

七、WindowStage 接口方法速查表

方法说明异步/同步
loadContent(path, callback)加载主页面内容回调
getMainWindowSync()同步获取主窗口同步
getMainWindow(callback)异步获取主窗口回调
createSubWindow(name, callback)创建应用子窗口回调
getLastWindow(callback)获取最上层子窗口回调
setWindowLayoutFullScreen(fullScreen)设置全屏布局异步

八、总结

WindowStage是 HarmonyOS 应用窗口管理的调度中心,开发者需要重点掌握:

  1. 生命周期管理:理解onWindowStageCreateonWindowStageDestroy的时机
  2. 页面加载loadContent是所有窗口操作的起点
  3. 主窗口获取getMainWindowSync获取主窗口后进行全屏、避让区域等设置
  4. 子窗口创建createSubWindow实现应用内悬浮窗效果
  5. 全局数据管理:通过AppStorage在 Ability 和页面间共享窗口信息
  6. 事件通信:通过eventHub实现 Ability 与页面的松耦合通信
  7. 状态管理V2:使用@ComponentV2+@Local替代 V1 装饰器,与AppStorage.get()配合使用

相关文档:

  • Interface (Window) 使用指南
  • Interface (AVPlayer) 使用指南
  • 简约风格悬浮窗效果案例指南
  • ArkTS 悬浮窗开发避坑指南