欢迎光临
我们一直在努力

HarmonyOS应用开发实战:小事记 - WindowStage 的创建销毁与窗口属性配置

页面预览

前言

在 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 的生命周期关系

UIAbility 回调WindowStage 状态说明
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 返回错误码。

检查清单:

  • 页面路径是否在 main_pages.json 中注册
  • 页面文件是否存在于 ets/pages/ 目录下
  • 页面文件中的 @Entry 装饰器是否正确
  • 导入路径是否正确
  • 8.2 窗口属性配置不生效

    问题:设置了窗口属性,但 UI 没有变化。

    可能原因:

  • 属性设置与页面加载的顺序问题
  • 系统主题或配置覆盖了应用设置
  • 调用了错误的窗口对象
  • 解决方案:

    // 确保在 loadContent 之前设置窗口属性
    onWindowStageCreate(windowStage: window.WindowStage): void {
    // 先配置窗口
    this.configureWindow(windowStage);
    // 再加载页面
    windowStage.loadContent('pages/Index');
    }

    总结

    本文从 xiaoshiji_ohos_app 的 EntryAbility.ets 出发,深入解析了 WindowStage 的创建销毁流程和窗口属性配置。核心要点如下:

  • WindowStage 是窗口管理的核心,在 onWindowStageCreate 中配置窗口、加载页面,在 onWindowStageDestroy 中释放资源
  • 窗口属性包括背景色、方向、全屏模式、系统栏等,需在页面加载前配置
  • 窗口事件监听支持窗口大小变化、焦点变化、可见性变化等,用于适配不同屏幕尺寸
  • 启动窗口背景色需要与首页背景色一致,消除视觉跳跃
  • 如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


    相关资源:

    • 官方文档 – 开发者指南:HarmonyOS 应用开发
    • 官方文档 – ArkUI 组件参考:ArkUI 组件
    • 官方文档 – API 参考:API 参考
    • 官方文档 – 状态管理:状态管理概述
    • 官方文档 – 动画:动画概述
    • 官方文档 – 网络管理:网络管理
    • 官方文档 – 数据管理:数据管理
    • 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
    赞(0)
    未经允许不得转载:171主机测评 » HarmonyOS应用开发实战:小事记 - WindowStage 的创建销毁与窗口属性配置
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址