
前言
在 HarmonyOS 的 Stage 模型中,WindowStage 是连接 UIAbility 与 Window 的桥梁。它不是 UIAbility 的附属品,而是一个独立的窗口管理阶段。WindowStage 的创建与销毁由系统自动调度,开发者在其回调中加载页面内容、配置窗口属性。掌握 WindowStage 的生命周期和窗口属性配置,是优化应用启动体验和适配不同屏幕尺寸的关键。本文以小事记(xiaoshiji_ohos_app) 的 EntryAbility.ets 为切入点,深入解析 WindowStage 的创建销毁流程、窗口属性配置方法和窗口事件监听。
核心特点:
- 简单易用:API 设计直观,上手成本低
- 性能优异:底层优化充分,运行效率高
- 扩展性强:支持自定义配置和扩展
本文参考 HarmonyOS 官方文档:application-lifecycle.md 和 Window 开发指南。
一、WindowStage 的角色定位
1.1 WindowStage 在应用架构中的位置
UIAbility
↓ 管理
WindowStage
↓ 管理
Window (主窗口 / 子窗口)
↓ 包含
UI 内容 (loadContent 加载的页面)
1.2 WindowStage 的核心职责
| 窗口创建 | 创建应用主窗口 | onWindowStageCreate 回调 |
| 页面加载 | 加载首页页面内容 | windowStage.loadContent() |
| 窗口属性配置 | 设置窗口大小、方向、背景色 | windowStage.getMainWindow() |
| 窗口事件监听 | 监听窗口大小变化、焦点变化 | windowStage.on('windowSizeChange') |
| 窗口销毁 | 释放窗口资源 | onWindowStageDestroy 回调 |
二、WindowStage 的生命周期
2.1 创建与销毁的时机
// EntryAbility.ets — WindowStage 的完整生命周期
import { UIAbility, Want, AbilityConstant } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0x0000;
export default class EntryAbility extends UIAbility {
// UIAbility 创建后,系统自动创建 WindowStage
// 然后回调 onWindowStageCreate
onWindowStageCreate(windowStage: window.WindowStage): void {
hilog.info(DOMAIN, 'testTag', 'WindowStage created');
// 1. 配置窗口属性
this.configureWindow(windowStage);
// 2. 加载页面内容
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag',
'Failed to load content: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, 'testTag', 'Content loaded successfully');
});
}
// UIAbility 销毁前,系统自动销毁 WindowStage
// 然后回调 onWindowStageDestroy
onWindowStageDestroy(): void {
hilog.info(DOMAIN, 'testTag', 'WindowStage destroyed');
// 在此处释放窗口相关资源
this.releaseWindowResources();
}
private async configureWindow(windowStage: window.WindowStage): Promise<void> {
try {
const mainWindow = await windowStage.getMainWindow();
// 设置窗口背景色,与首页背景一致
await mainWindow.setWindowBackgroundColor('#F8F9FA');
// 设置窗口为竖屏模式
await mainWindow.setWindowPreferredOrientation(
window.Orientation.PORTRAIT
);
// 禁用全屏布局
await mainWindow.setWindowLayoutFullScreen(false);
// 显示状态栏和导航栏
await mainWindow.setWindowSystemBarEnable(['status', 'navigation']);
} catch (err) {
hilog.error(DOMAIN, 'testTag',
'Failed to configure window: %{public}s', JSON.stringify(err));
}
}
private releaseWindowResources(): void {
// 释放窗口相关资源
hilog.info(DOMAIN, 'testTag', 'Window resources released');
}
}
2.2 WindowStage 与 UIAbility 的生命周期关系
| onCreate | 未创建 | Ability 刚创建,窗口尚未初始化 |
| onWindowStageCreate | 已创建 | WindowStage 创建完成,可配置窗口 |
| onForeground | 活跃 | 窗口可见,可交互 |
| onBackground | 不活跃 | 窗口不可见,但未销毁 |
| onWindowStageDestroy | 销毁中 | 窗口即将销毁,释放资源 |
| onDestroy | 已销毁 | WindowStage 已销毁 |
三、窗口属性的配置
3.1 窗口属性一览
| 背景色 | setWindowBackgroundColor | 颜色值 | 窗口背景色,建议与首页背景一致 |
| 方向 | setWindowPreferredOrientation | PORTRAIT / LANDSCAPE / AUTO | 横竖屏模式 |
| 全屏 | setWindowLayoutFullScreen | true / false | 是否启用全屏布局 |
| 系统栏 | setWindowSystemBarEnable | ['status'] / ['navigation'] | 状态栏和导航栏显隐 |
| 亮度 | setWindowBrightness | 0.0 ~ 1.0 | 窗口亮度 |
| 是否可触摸 | setWindowTouchable | true / false | 触摸事件的启用/禁用 |
| 窗口大小 | setWindowMinWidth / setWindowMinHeight | 像素值 | 窗口最小尺寸(自由窗口模式) |
3.2 窗口属性的完整配置
// 窗口属性的完整配置
private async configureFullWindow(windowStage: window.WindowStage): Promise<void> {
const mainWindow = await windowStage.getMainWindow();
// 1. 设置窗口背景色
await mainWindow.setWindowBackgroundColor('#F8F9FA');
// 2. 设置窗口方向为竖屏
await mainWindow.setWindowPreferredOrientation(
window.Orientation.PORTRAIT
);
// 3. 禁用全屏布局(保留状态栏和导航栏)
await mainWindow.setWindowLayoutFullScreen(false);
// 4. 显示状态栏和导航栏
await mainWindow.setWindowSystemBarEnable(['status', 'navigation']);
// 5. 设置状态栏文字颜色为深色(浅色背景时使用)
await mainWindow.setWindowSystemBarProperties({
statusBarContentColor: '#1A1A2E',
navigationBarContentColor: '#1A1A2E'
});
// 6. 设置窗口亮度
await mainWindow.setWindowBrightness(1.0);
// 7. 设置窗口可触摸
await mainWindow.setWindowTouchable(true);
}
3.3 窗口方向的配置策略
| PORTRAIT | 1 | 竖屏应用(推荐,小事记使用) |
| LANDSCAPE | 2 | 横屏应用(如游戏、视频播放) |
| AUTO_ROTATION | 3 | 自动旋转(跟随设备方向) |
| AUTO_ROTATION_PORTRAIT | 4 | 竖屏自动旋转 |
| AUTO_ROTATION_LANDSCAPE | 5 | 横屏自动旋转 |
| AUTO_ROTATION_RESTRICTED | 6 | 受限自动旋转 |
四、窗口事件的监听
4.1 窗口大小变化监听
// 监听窗口大小变化
onWindowStageCreate(windowStage: window.WindowStage): void {
try {
windowStage.on('windowSizeChange', (data: window.Size) => {
hilog.info(DOMAIN, 'testTag',
`Window size changed: ${data.width}x${data.height}`);
// 横竖屏切换时调整布局
if (data.width > data.height) {
hilog.info(DOMAIN, 'testTag', 'Landscape mode');
this.adjustLayoutForLandscape();
} else {
hilog.info(DOMAIN, 'testTag', 'Portrait mode');
this.adjustLayoutForPortrait();
}
});
} catch (err) {
hilog.error(DOMAIN, 'testTag',
'Failed to register window size change: %{public}s', JSON.stringify(err));
}
}
private adjustLayoutForLandscape(): void {
// 横屏布局调整
// 例如:增加列表的列数,调整卡片尺寸
}
private adjustLayoutForPortrait(): void {
// 竖屏布局调整
// 例如:恢复默认布局
}
4.2 窗口焦点变化监听
// 监听窗口焦点变化
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.on('windowFocusChange', (isFocused: boolean) => {
if (isFocused) {
hilog.info(DOMAIN, 'testTag', 'Window gained focus');
// 窗口获得焦点:恢复动画、刷新数据
this.resumeAnimations();
} else {
hilog.info(DOMAIN, 'testTag', 'Window lost focus');
// 窗口失去焦点:暂停动画、保存数据
this.pauseAnimations();
this.saveDraftData();
}
});
}
4.3 窗口事件列表
| windowSizeChange | Size | 窗口大小变化时 |
| windowFocusChange | boolean | 窗口焦点变化时 |
| windowVisibilityChange | boolean | 窗口可见性变化时 |
| windowDisplayIdChange | number | 窗口所在屏幕变化时 |
| windowStatusChange | WindowStatusType | 窗口状态变化时 |
五、loadContent 的异步加载
5.1 loadContent 的回调处理
windowStage.loadContent() 是异步操作,需要通过回调或 Promise 获取加载结果:
// 使用回调方式
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag',
'Failed to load content: %{public}s', JSON.stringify(err));
// 页面加载失败的处理
this.handleLoadContentError(err);
return;
}
hilog.info(DOMAIN, 'testTag', 'Content loaded successfully');
});
// 封装为 Promise 方式
private loadContentAsync(windowStage: window.WindowStage, page: string): Promise<void> {
return new Promise((resolve, reject) => {
windowStage.loadContent(page, (err) => {
if (err.code) {
reject(err);
} else {
resolve();
}
});
});
}
5.2 页面加载失败的处理
// 页面加载失败的处理策略
private handleLoadContentError(err: BusinessError): void {
switch (err.code) {
case 200007:
// 页面路径未注册
hilog.error(DOMAIN, 'testTag', 'Page path not registered in main_pages.json');
break;
case 200008:
// 页面文件不存在
hilog.error(DOMAIN, 'testTag', 'Page file not found');
break;
default:
// 其他错误
hilog.error(DOMAIN, 'testTag', 'Unknown error: %{public}s', err.message);
}
}
六、窗口属性配置的最佳实践
6.1 启动窗口背景色的一致性
// 确保启动窗口背景色与首页背景色一致
// module.json5 中配置
"startWindowBackground": "$color:start_window_background"
// resources/base/element/color.json
{
"color": [
{
"name": "start_window_background",
"value": "#F8F9FA" // 与 HomePage 的背景色一致
}
]
}
// 在 onWindowStageCreate 中设置窗口背景色
await mainWindow.setWindowBackgroundColor('#F8F9FA');
6.2 窗口属性的设置时机
| 背景色 | onWindowStageCreate 中 | 需要在页面加载之前设置 |
| 方向 | onWindowStageCreate 中 | 在页面加载前确定方向 |
| 全屏模式 | onWindowStageCreate 中 | 在页面加载前确定布局范围 |
| 系统栏 | onWindowStageCreate 中 | 在页面加载前确定安全区域 |
| 亮度 | onWindowStageCreate 中 | 可在页面加载后设置 |
| 窗口大小 | 运行时按需设置 | 自由窗口模式下使用 |
七、多窗口场景
7.1 创建子窗口
// 创建子窗口(如悬浮窗)
async function createSubWindow(windowStage: window.WindowStage): Promise<void> {
try {
const subWindow = await windowStage.createSubWindow('subWindow');
await subWindow.setWindowLayoutFullScreen(false);
await subWindow.setWindowBackgroundColor('#FFFFFF');
await subWindow.showWindow();
await subWindow.loadContent('pages/SubPage');
} catch (err) {
console.error(`创建子窗口失败: ${err.message}`);
}
}
7.2 窗口属性对比
| 创建方式 | 系统自动创建 | windowStage.createSubWindow() |
| 生命周期 | 跟随 UIAbility | 手动管理 |
| 位置 | 全屏 | 可自定义位置和大小 |
| 用途 | 应用主界面 | 悬浮窗、弹框、辅助界面 |
八、常见问题与解决方案
8.1 loadContent 加载失败
问题:windowStage.loadContent 返回错误码。
检查清单:
8.2 窗口属性配置不生效
问题:设置了窗口属性,但 UI 没有变化。
可能原因:
解决方案:
// 确保在 loadContent 之前设置窗口属性
onWindowStageCreate(windowStage: window.WindowStage): void {
// 先配置窗口
this.configureWindow(windowStage);
// 再加载页面
windowStage.loadContent('pages/Index');
}
总结
本文从 xiaoshiji_ohos_app 的 EntryAbility.ets 出发,深入解析了 WindowStage 的创建销毁流程和窗口属性配置。核心要点如下:
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- 官方文档 – 开发者指南:HarmonyOS 应用开发
- 官方文档 – ArkUI 组件参考:ArkUI 组件
- 官方文档 – API 参考:API 参考
- 官方文档 – 状态管理:状态管理概述
- 官方文档 – 动画:动画概述
- 官方文档 – 网络管理:网络管理
- 官方文档 – 数据管理:数据管理
- 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net






