《悬浮窗效果》二、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 生命周期中自动创建并传入,开发者无需手动创建:
export default class EntryAbility extends UIAbility {
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()
同步获取应用主窗口实例。
let mainWindow: window.Window = windowStage.getMainWindowSync();
获取主窗口后,可以进行以下操作:
// 获取UI上下文
let uiContext = mainWindow.getUIContext();
// 获取窗口属性
let props = mainWindow.getWindowProperties();
let windowId = props.id;
// 设置全屏
mainWindow.setWindowLayoutFullScreen(true);
// 获取避让区域
let avoidArea = 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 回调中通过主窗口设置
let mainWindow = 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';
const DOMAIN = 0x0000;
export default class EntryAbility extends UIAbility {
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上下文并存储到AppStorage
let mainWindow = windowStage.getMainWindowSync();
let uiContext = mainWindow.getUIContext();
AppStorage.setOrCreate('uiContext', uiContext);
// Step 3: 存储windowStage供页面使用
AppStorage.setOrCreate('windowStage', windowStage);
// Step 4: 存储主窗口ID
AppStorage.setOrCreate('mainWindowId',
mainWindow.getWindowProperties().id);
// Step 5: 设置全屏布局
mainWindow.setWindowLayoutFullScreen(true);
// Step 6: 获取状态栏避让区域
let sysAvoidArea = mainWindow.getWindowAvoidArea(
window.AvoidAreaType.TYPE_SYSTEM);
let topRectHeight = sysAvoidArea.topRect.height;
AppStorage.setOrCreate('topRectHeight', topRectHeight);
// Step 7: 获取导航条避让区域
let navAvoidArea = mainWindow.getWindowAvoidArea(
window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);
let bottomRectHeight = 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
@ComponentV2
struct Index {
@Local windowStage: window.WindowStage =
AppStorage.get('windowStage') as window.WindowStage;
@Local isSubWindowCreated: 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');
});
// 设置位置和大小
let uiContext = this.windowStage.getMainWindowSync().getUIContext();
subWin.moveWindowTo(0, 300);
subWin.resize(uiContext.vp2px(60), uiContext.vp2px(60));
// 显示子窗口
subWin.showWindow();
this.isSubWindowCreated = true;
});
}
// 销毁子窗口
async destroySubWindow(): Promise<void> {
try {
let subWin = window.findWindow('demoSubWin');
await subWin.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(() => {
let subId = window.findWindow('subWin').getWindowProperties().id;
let mainId = windowStage.getMainWindowSync().getWindowProperties().id;
window.shiftAppWindowFocus(subId, mainId);
}, 500);
5.2 EventHub 事件通信
通过 eventHub 实现 Ability 与页面之间的事件通信:
// EntryAbility 中发送事件
onForeground(): void {
this.context.eventHub.emit('onForeground');
}
// 页面中监听事件
aboutToAppear(): void {
let ctx = this.getUIContext().getHostContext();
ctx?.eventHub.on('onForeground', () => {
// 应用回到前台时的处理逻辑
});
}
aboutToDisappear(): void {
let ctx = 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 {
let existing = window.findWindow('subWinName');
// 已存在,直接显示
existing.showWindow();
} catch (err) {
// 不存在,创建新窗口
windowStage.createSubWindow('subWinName', callback);
}
6.4 应用退出时清理子窗口
onBackground(): void {
// 应用进入后台时,可选择隐藏或销毁子窗口
try {
let subWin = window.findWindow('subWinName');
subWin.hideWindow();
} catch (err) {
// 子窗口不存在
}
}
七、WindowStage 接口方法速查表
| 方法 | 说明 | 异步/同步 |
|---|---|---|
loadContent(path, callback) |
加载主页面内容 | 回调 |
getMainWindowSync() |
同步获取主窗口 | 同步 |
getMainWindow(callback) |
异步获取主窗口 | 回调 |
createSubWindow(name, callback) |
创建应用子窗口 | 回调 |
getLastWindow(callback) |
获取最上层子窗口 | 回调 |
setWindowLayoutFullScreen(fullScreen) |
设置全屏布局 | 异步 |
八、总结
WindowStage 是 HarmonyOS 应用窗口管理的调度中心,开发者需要重点掌握:
- 生命周期管理:理解
onWindowStageCreate和onWindowStageDestroy的时机 - 页面加载:
loadContent是所有窗口操作的起点 - 主窗口获取:
getMainWindowSync获取主窗口后进行全屏、避让区域等设置 - 子窗口创建:
createSubWindow实现应用内悬浮窗效果 - 全局数据管理:通过
AppStorage在 Ability 和页面间共享窗口信息 - 事件通信:通过
eventHub实现 Ability 与页面的松耦合通信 - 状态管理V2:使用
@ComponentV2+@Local替代 V1 装饰器,与AppStorage.get()配合使用
相关文档:
更多推荐



所有评论(0)