HarmonyOS窗口管理——窗口属性设置与沉浸式体验实现
HarmonyOS的窗口模块在同一块物理屏幕上提供多个应用界面显示和交互的机制。对应用开发者而言,窗口模块提供了界面显示和交互能力;对终端用户而言,提供了控制应用界面的方式;对整个操作系统而言,则提供了不同应用界面的组织管理逻辑。窗口管理是HarmonyOS应用开发的核心能力之一。窗口生命周期管理:理解SHOWN、RESUMED、PAUSED、HIDDEN等状态多类型窗口创建:主窗口、子窗口、悬浮
1. 窗口管理概述
HarmonyOS的窗口模块在同一块物理屏幕上提供多个应用界面显示和交互的机制。对应用开发者而言,窗口模块提供了界面显示和交互能力;对终端用户而言,提供了控制应用界面的方式;对整个操作系统而言,则提供了不同应用界面的组织管理逻辑。
1.1 窗口模块的核心职责
窗口模块在HarmonyOS中承担以下关键职责:
- 提供窗口对象:为应用和系统界面提供窗口对象,开发者通过窗口加载UI界面实现显示功能
- 组织显示关系:维护不同窗口间的叠加层次和位置属性(Z轴高度)
- 提供窗口装饰:包括窗口标题栏和边框,系统默认提供且可配置启用/禁用
- 提供窗口动效:窗口显示、隐藏及切换时的动画效果,为系统默认行为
- 指导输入事件分发:根据窗口状态和焦点进行触摸、鼠标和键盘事件分发
1.2 窗口分类体系
HarmonyOS将窗口分为两大基本类型:
系统窗口:完成系统特定功能的窗口,如音量条、壁纸、通知栏、状态栏、导航栏等。
应用窗口:与应用显示相关的窗口,进一步分为:
- 应用主窗口:显示应用主界面,在任务管理界面显示
- 应用子窗口:用于弹窗、悬浮窗等辅助窗口,生命周期跟随应用主窗口,不在任务管理界面显示
1.3 窗口模式支持
HarmonyOS支持三种应用窗口模式:
- 全屏模式:应用主窗口启动时铺满整个屏幕
- 分屏模式:支持二分屏,可拖拽分界线调整窗口尺寸
- 自由窗口:大小和位置可自由改变,支持多窗口同时显示
2. Stage模型下的窗口管理
在Stage模型下,窗口管理采用层次化架构:一个UIAbility对应一个WindowStage,一个WindowStage对应一个应用主窗口。UIAbility通过WindowStage管理主窗口并维护其生命周期。
2.1 窗口生命周期管理
窗口在进入前台、前后台切换及退后台时,会触发相应的生命周期状态变化:
| 状态 | 触发场景 | 描述 |
|---|---|---|
| SHOWN | 应用全屏启动、悬浮窗被拉起 | 窗口进入到前台 |
| RESUMED | 应用全屏启动、应用上滑悬停后回到应用 | 窗口进入可交互状态 |
| PAUSED | 应用退后台回到桌面、全屏状态下被系统管控 | 窗口进入不可交互状态 |
| HIDDEN | 应用全屏状态上滑退后台回到桌面 | 窗口进入到后台 |
生命周期监听示例:
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
import { BusinessError } from '@kit.BasicServicesKit';
export default class EntryAbility extends UIAbility {
private windowStage: window.WindowStage | null = null;
onWindowStageCreate(windowStage: window.WindowStage): void {
this.windowStage = windowStage;
// API version 20+ 推荐使用的新接口
windowStage.on('windowStageLifecycleEvent', (stageEvent: window.WindowStageEventType) => {
switch (stageEvent) {
case window.WindowStageEventType.SHOWN:
console.info('WindowStage event: SHOWN');
this.handleWindowShown();
break;
case window.WindowStageEventType.RESUMED:
console.info('WindowStage event: RESUMED');
this.handleWindowResumed();
break;
case window.WindowStageEventType.PAUSED:
console.info('WindowStage event: PAUSED');
this.handleWindowPaused();
break;
case window.WindowStageEventType.HIDDEN:
console.info('WindowStage event: HIDDEN');
this.handleWindowHidden();
break;
}
});
// 传统监听方式(API version < 20)
windowStage.on('windowStageEvent', (data: window.WindowStageEventType) => {
console.info(`Traditional event: ${data}`);
});
this.setupMainWindow();
}
private setupMainWindow(): void {
if (!this.windowStage) return;
// 获取主窗口
this.windowStage.getMainWindow((err: BusinessError, mainWindow: window.Window) => {
if (err) {
console.error(`Failed to get main window. Code: ${err.code}, message: ${err.message}`);
return;
}
// 设置窗口属性
this.configureWindowProperties(mainWindow);
});
// 加载主页面
this.windowStage.loadContent('pages/Index', (err: BusinessError) => {
if (err) {
console.error(`Failed to load the content. Code: ${err.code}, message: ${err.message}`);
}
});
}
private handleWindowShown(): void {
// 窗口显示处理:恢复动画、刷新数据等
}
private handleWindowResumed(): void {
// 窗口可交互:恢复音频、继续动画等
}
private handleWindowPaused(): void {
// 窗口不可交互:暂停音频、停止动画等
}
private handleWindowHidden(): void {
// 窗口隐藏:释放非必要资源
}
onWindowStageDestroy(): void {
// 清理资源
if (this.windowStage) {
this.windowStage.off('windowStageLifecycleEvent');
this.windowStage.off('windowStageEvent');
this.windowStage = null;
}
}
}
3. 应用窗口属性设置
3.1 主窗口配置
主窗口是应用的主要界面载体,需要在UIAbility的onWindowStageCreate回调中进行配置。
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
import { BusinessError } from '@kit.BasicServicesKit';
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
// 获取主窗口
windowStage.getMainWindow((err: BusinessError, mainWindow: window.Window) => {
if (err) {
console.error(`Failed to obtain main window: ${JSON.stringify(err)}`);
return;
}
// 设置窗口背景色
mainWindow.setWindowBackgroundColor('#F5F5F5').then(() => {
console.info('Succeeded in setting window background color.');
}).catch((error: BusinessError) => {
console.error(`Failed to set background color. Code: ${error.code}, message: ${error.message}`);
});
// 设置窗口亮度(0.0-1.0)
mainWindow.setWindowBrightness(0.8).then(() => {
console.info('Succeeded in setting window brightness.');
}).catch((error: BusinessError) => {
console.error(`Failed to set brightness. Code: ${error.code}, message: ${error.message}`);
});
// 设置窗口可触摸
mainWindow.setWindowTouchable(true).then(() => {
console.info('Succeeded in setting window touchable.');
}).catch((error: BusinessError) => {
console.error(`Failed to set touchable. Code: ${error.code}, message: ${error.message}`);
});
// 设置窗口保持常亮
mainWindow.setWindowKeepScreenOn(true).then(() => {
console.info('Succeeded in setting keep screen on.');
}).catch((error: BusinessError) => {
console.error(`Failed to set keep screen on. Code: ${error.code}, message: ${error.message}`);
});
});
// 加载主页面
windowStage.loadContent('pages/Index', (err: BusinessError) => {
if (err) {
console.error(`Failed to load content. Code: ${err.code}, message: ${err.message}`);
return;
}
console.info('Succeeded in loading content.');
});
}
}
3.2 子窗口创建与管理
子窗口用于弹窗、悬浮窗等辅助界面,生命周期依赖于主窗口。
import window from '@ohos.window';
import { BusinessError } from '@kit.BasicServicesKit';
class SubWindowManager {
private subWindow: window.Window | null = null;
private windowStage: window.WindowStage;
constructor(windowStage: window.WindowStage) {
this.windowStage = windowStage;
}
// 创建子窗口
async createSubWindow(windowName: string, contentPath: string): Promise<void> {
return new Promise((resolve, reject) => {
this.windowStage.createSubWindow(windowName, (err: BusinessError, windowObj: window.Window) => {
if (err) {
console.error(`Failed to create sub window: ${JSON.stringify(err)}`);
reject(err);
return;
}
this.subWindow = windowObj;
console.info('Succeeded in creating sub window.');
// 设置子窗口属性
this.configureSubWindow(contentPath)
.then(() => resolve())
.catch((error) => reject(error));
});
});
}
private async configureSubWindow(contentPath: string): Promise<void> {
if (!this.subWindow) return;
try {
// 设置窗口位置和大小
await this.subWindow.moveWindowTo(300, 200);
await this.subWindow.resize(800, 600);
// 设置窗口背景透明
await this.subWindow.setWindowBackgroundColor('#00000000');
// 设置为模态窗口
await this.subWindow.setWindowModal(true);
// 加载内容
await this.subWindow.setUIContent(contentPath);
// 注册窗口外部点击事件
this.subWindow.on('touchOutside', () => {
this.hideSubWindow();
});
console.info('Sub window configured successfully.');
} catch (error) {
const err = error as BusinessError;
console.error(`Failed to configure sub window. Code: ${err.code}, message: ${err.message}`);
throw error;
}
}
// 显示子窗口
async showSubWindow(): Promise<void> {
if (!this.subWindow) {
console.error('Sub window not created');
return;
}
try {
await this.subWindow.showWindow();
console.info('Sub window shown successfully.');
} catch (error) {
const err = error as BusinessError;
console.error(`Failed to show sub window. Code: ${err.code}, message: ${err.message}`);
}
}
// 隐藏子窗口
async hideSubWindow(): Promise<void> {
if (!this.subWindow) return;
try {
await this.subWindow.hideWindow();
console.info('Sub window hidden successfully.');
} catch (error) {
const err = error as BusinessError;
console.error(`Failed to hide sub window. Code: ${err.code}, message: ${err.message}`);
}
}
// 销毁子窗口
async destroySubWindow(): Promise<void> {
if (!this.subWindow) return;
try {
await this.subWindow.destroyWindow();
this.subWindow = null;
console.info('Sub window destroyed successfully.');
} catch (error) {
const err = error as BusinessError;
console.error(`Failed to destroy sub window. Code: ${err.code}, message: ${err.message}`);
}
}
}
export default SubWindowManager;
3.3 悬浮窗创建(需要系统权限)
悬浮窗是特殊的应用窗口,具备在应用退至后台后仍然在前台显示的能力。
import window from '@ohos.window';
import { BusinessError } from '@kit.BasicServicesKit';
import UIAbility from '@ohos.app.ability.UIAbility';
export default class FloatWindowManager {
private floatWindow: window.Window | null = null;
// 创建悬浮窗(需要ohos.permission.SYSTEM_FLOAT_WINDOW权限)
async createFloatWindow(context: any, contentPath: string): Promise<void> {
try {
const config: window.WindowConfiguration = {
name: 'floatWindow',
windowType: window.WindowType.TYPE_FLOAT,
ctx: context
};
this.floatWindow = await window.createWindow(config);
// 设置悬浮窗属性
await this.floatWindow.moveWindowTo(100, 100);
await this.floatWindow.resize(400, 300);
await this.floatWindow.setWindowLayoutFullScreen(false);
// 设置窗口背景色
await this.floatWindow.setWindowBackgroundColor('#FFFFFF');
// 加载内容
await this.floatWindow.setUIContent(contentPath);
console.info('Float window created successfully.');
} catch (error) {
const err = error as BusinessError;
console.error(`Failed to create float window. Code: ${err.code}, message: ${err.message}`);
throw error;
}
}
// 显示悬浮窗
async showFloatWindow(): Promise<void> {
if (!this.floatWindow) {
console.error('Float window not created');
return;
}
try {
await this.floatWindow.showWindow();
console.info('Float window shown successfully.');
} catch (error) {
const err = error as BusinessError;
console.error(`Failed to show float window. Code: ${err.code}, message: ${err.message}`);
}
}
// 更新悬浮窗位置
async updateFloatWindowPosition(x: number, y: number): Promise<void> {
if (!this.floatWindow) return;
try {
await this.floatWindow.moveWindowTo(x, y);
console.info('Float window position updated.');
} catch (error) {
const err = error as BusinessError;
console.error(`Failed to update position. Code: ${err.code}, message: ${err.message}`);
}
}
}
权限配置(在module.json5中):
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.SYSTEM_FLOAT_WINDOW",
"reason": "用于创建全局悬浮窗",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "always"
}
}
]
}
}
4. 沉浸式体验实现
沉浸式体验通过控制状态栏、导航栏等系统窗口,减少系统界面的突兀感,为用户提供最佳体验。
4.1 沉浸式实现方案
方案一:隐藏系统栏(全沉浸式)
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
import { BusinessError } from '@kit.BasicServicesKit';
export default class ImmersiveAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.getMainWindow((err: BusinessError, mainWindow: window.Window) => {
if (err) {
console.error(`Failed to get main window: ${JSON.stringify(err)}`);
return;
}
// 设置全屏布局
mainWindow.setWindowLayoutFullScreen(true).then(() => {
console.info('Succeeded in setting full screen layout.');
// 隐藏状态栏和导航栏
return mainWindow.setWindowSystemBarEnable([]);
}).then(() => {
console.info('Succeeded in hiding system bars.');
// 设置系统栏颜色与界面融合
return this.setupSystemBarProperties(mainWindow);
}).catch((error: BusinessError) => {
console.error(`Failed to setup immersive mode. Code: ${error.code}, message: ${error.message}`);
});
});
windowStage.loadContent('pages/ImmersivePage', (err: BusinessError) => {
if (err) {
console.error(`Failed to load content. Code: ${err.code}, message: ${err.message}`);
}
});
}
private async setupSystemBarProperties(mainWindow: window.Window): Promise<void> {
const systemBarProperties: window.SystemBarProperties = {
statusBarColor: '#00000000', // 完全透明
statusBarContentColor: '#FFFFFF', // 状态栏内容颜色(白色)
navigationBarColor: '#00000000',
isStatusBarLightIcon: true,
isNavigationBarLightIcon: true
};
try {
await mainWindow.setWindowSystemBarProperties(systemBarProperties);
console.info('Succeeded in setting system bar properties.');
} catch (error) {
const err = error as BusinessError;
console.error(`Failed to set system bar properties. Code: ${err.code}, message: ${err.message}`);
throw error;
}
}
}
方案二:避让区适配(内容延伸)
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
import { BusinessError } from '@kit.BasicServicesKit';
export default class SafeAreaAbility extends UIAbility {
private avoidAreaChangeCallback: (data: window.AvoidArea) => void | null = null;
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.getMainWindow((err: BusinessError, mainWindow: window.Window) => {
if (err) {
console.error(`Failed to get main window: ${JSON.stringify(err)}`);
return;
}
this.setupSafeAreaHandling(mainWindow);
});
windowStage.loadContent('pages/SafeAreaPage', (err: BusinessError) => {
if (err.code) {
console.error(`Failed to load content. Code: ${err.code}, message: ${err.message}`);
}
});
}
private setupSafeAreaHandling(mainWindow: window.Window): void {
// 设置全屏布局
mainWindow.setWindowLayoutFullScreen(true).then(() => {
// 获取初始避让区域
const systemAvoidArea = mainWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
const indicatorAvoidArea = mainWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);
this.updateSafeAreaInsets(systemAvoidArea, indicatorAvoidArea);
// 监听避让区域变化
this.avoidAreaChangeCallback = (data: window.AvoidArea) => {
console.info(`Avoid area changed: ${JSON.stringify(data)}`);
this.handleAvoidAreaChange(data);
};
mainWindow.on('avoidAreaChange', this.avoidAreaChangeCallback);
}).catch((error: BusinessError) => {
console.error(`Failed to setup safe area. Code: ${error.code}, message: ${error.message}`);
});
}
private handleAvoidAreaChange(data: window.AvoidArea): void {
// 处理避让区域变化,更新UI布局
const systemArea = data.type === window.AvoidAreaType.TYPE_SYSTEM ?
data.area : this.getCurrentSystemAvoidArea();
const indicatorArea = data.type === window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR ?
data.area : this.getCurrentIndicatorAvoidArea();
this.updateSafeAreaInsets(systemArea, indicatorArea);
}
private updateSafeAreaInsets(systemArea: window.AvoidArea, indicatorArea: window.AvoidArea): void {
// 更新安全区域边距,可通过AppStorage共享给UI组件
const safeAreaInsets = {
top: systemArea.topRect.height,
bottom: indicatorArea.bottomRect.height,
left: systemArea.leftRect.width,
right: systemArea.rightRect.width
};
// 存储安全区域信息供UI组件使用
AppStorage.setOrCreate('safeAreaInsets', safeAreaInsets);
}
onWindowStageDestroy(): void {
// 清理监听器
if (this.avoidAreaChangeCallback) {
// 需要获取mainWindow实例来取消监听,实际项目中应妥善管理
this.avoidAreaChangeCallback = null;
}
}
}
4.2 UI组件安全区域适配
在UI组件中正确处理安全区域,确保内容不被系统UI遮挡。
@Entry
@Component
struct ImmersiveVideoPlayer {
@StorageProp('safeAreaInsets') safeAreaInsets?: {
top: number;
bottom: number;
left: number;
right: number;
};
build() {
Stack({ alignContent: Alignment.TopStart }) {
// 视频播放器 - 扩展到全屏
VideoPlayer({
src: $rawfile('sample.mp4'),
controller: new VideoController()
})
.width('100%')
.height('100%')
.expandSafeArea([SafeAreaType.SYSTEM],
[SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
// 顶部控制栏 - 避让状态栏
Column() {
Row() {
Image($r('app.media.ic_back'))
.width(24)
.height(24)
.onClick(() => {})
Text('视频标题')
.fontSize(18)
.fontColor(Color.White)
.margin({ left: 12 })
Blank()
Image($r('app.media.ic_more'))
.width(24)
.height(24)
.onClick(() => {})
}
.width('100%')
.padding(12)
}
.width('100%')
.backgroundColor('#CC000000')
.padding({
top: this.safeAreaInsets?.top ? this.safeAreaInsets.top + 12 : 12
})
// 底部控制栏 - 避让导航栏
Column() {
Slider({ value: 0, min: 0, max: 100 })
.width('100%')
.height(4)
Row() {
Text('00:00')
.fontSize(14)
.fontColor(Color.White)
Blank()
Row() {
Image($r('app.media.ic_play'))
.width(32)
.height(32)
.onClick(() => {})
Image($r('app.media.ic_fullscreen'))
.width(32)
.height(32)
.onClick(() => {})
}
}
.width('100%')
}
.width('100%')
.padding(12)
.align(Alignment.Bottom)
.padding({
bottom: this.safeAreaInsets?.bottom ? this.safeAreaInsets.bottom + 12 : 12
})
}
.width('100%')
.height('100%')
.backgroundColor(Color.Black)
}
}
5. 高级窗口特性
5.1 画中画(Picture-in-Picture)功能
画中画功能允许视频内容在小窗口中播放,同时用户可进行其他操作。
import pipWindow from '@ohos.pipWindow';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct VideoPlayerWithPIP {
private pipController: pipWindow.PiPController | null = null;
private isPipSupported: boolean = false;
aboutToAppear(): void {
// 检查系统是否支持画中画
this.isPipSupported = pipWindow.isPiPEnabled();
}
// 初始化画中画控制器
private async initializePip(): Promise<void> {
if (!this.isPipSupported) {
console.error('Picture-in-Picture is not supported on this device');
return;
}
try {
const config: pipWindow.PiPConfiguration = {
context: getContext(this) as Context,
navigationId: 'videoPlayer',
templateType: pipWindow.PiPTemplateType.VIDEO_PLAY,
contentWidth: 1920,
contentHeight: 1080,
controlGroups: [pipWindow.VideoPlayControlGroup.PLAY_PAUSE]
};
this.pipController = await pipWindow.create(config);
this.setupPipListeners();
} catch (error) {
const err = error as BusinessError;
console.error(`Failed to initialize PIP. Code: ${err.code}, message: ${err.message}`);
}
}
private setupPipListeners(): void {
if (!this.pipController) return;
// 监听画中画状态变化
this.pipController.on('stateChange', (state: pipWindow.PiPState, reason: string) => {
console.info(`PIP state changed to: ${state}, reason: ${reason}`);
switch (state) {
case pipWindow.PiPState.ENTERED:
this.onPipEntered();
break;
case pipWindow.PiPState.EXITED:
this.onPipExited();
break;
}
});
// 监听控制面板操作
this.pipController.on('controlPanelActionEvent',
(event: pipWindow.PiPActionEventType, status?: number) => {
this.handlePipControlEvent(event, status);
});
}
// 启动画中画
private async enterPipMode(): Promise<void> {
if (!this.pipController) {
await this.initializePip();
}
try {
await this.pipController?.startPiP();
console.info('PIP mode started successfully');
} catch (error) {
const err = error as BusinessError;
console.error(`Failed to start PIP. Code: ${err.code}, message: ${err.message}`);
}
}
build() {
Column() {
// 视频播放器组件
VideoComponent({ onEnterPip: () => this.enterPipMode() })
// 画中画控制按钮
Button('进入画中画模式')
.enabled(this.isPipSupported)
.onClick(() => this.enterPipMode())
.margin(20)
}
}
}
5.2 窗口元数据配置
通过module.json5中的metadata标签配置窗口属性。
{
"module": {
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"metadata": [
{
"name": "ohos.ability.window.width",
"value": "1200"
},
{
"name": "ohos.ability.window.height",
"value": "800"
},
{
"name": "ohos.ability.window.isMaximize",
"value": "false"
},
{
"name": "ohos.remove.starting.window",
"value": "false"
}
]
}
]
}
}
6. 最佳实践与性能优化
6.1 窗口管理最佳实践
- 及时释放资源:在窗口销毁时取消事件监听,释放窗口引用
- 合理使用子窗口:避免创建过多子窗口,及时销毁不再需要的窗口
- 内存管理:大尺寸窗口或包含复杂内容的窗口应在不可见时释放资源
- 用户体验:沉浸式模式提供明确的退出方式,避免用户困惑
6.2 性能优化建议
class OptimizedWindowManager {
private windows: Map<string, window.Window> = new Map();
private eventCallbacks: Map<string, Function> = new Map();
// 延迟创建窗口
async createWindowLazy(config: window.WindowConfiguration,
contentPath: string): Promise<window.Window> {
if (this.windows.has(config.name || 'default')) {
return this.windows.get(config.name || 'default')!;
}
const windowObj = await window.createWindow(config);
await windowObj.setUIContent(contentPath);
this.windows.set(config.name || 'default', windowObj);
return windowObj;
}
// 窗口复用
async reuseOrCreateWindow(config: window.WindowConfiguration,
contentPath: string): Promise<window.Window> {
const existingWindow = this.windows.get(config.name || 'default');
if (existingWindow) {
// 重用现有窗口,只需更新内容
await existingWindow.setUIContent(contentPath);
return existingWindow;
}
return this.createWindowLazy(config, contentPath);
}
// 智能销毁:当内存紧张时自动销毁非活跃窗口
onMemoryWarning(): void {
this.windows.forEach((win, name) => {
if (!win.isShowing()) {
win.destroyWindow();
this.windows.delete(name);
}
});
}
// 清理所有资源
cleanup(): void {
this.windows.forEach((win, name) => {
win.destroyWindow();
});
this.windows.clear();
this.eventCallbacks.clear();
}
}
7. 总结
窗口管理是HarmonyOS应用开发的核心能力之一。通过本文的学习,您应该掌握:
- 窗口生命周期管理:理解SHOWN、RESUMED、PAUSED、HIDDEN等状态
- 多类型窗口创建:主窗口、子窗口、悬浮窗的创建与配置
- 沉浸式体验实现:系统栏控制、安全区域适配、避让区处理
- 高级特性应用:画中画功能、窗口元数据配置
- 性能优化实践:资源管理、窗口复用、内存优化
正确的窗口管理不仅能提升用户体验,还能优化应用性能。在实际开发中,应根据具体场景选择合适的窗口策略,平衡功能需求与性能要求。
需要参加鸿蒙认证的请点击 鸿蒙认证链接
更多推荐


所有评论(0)