HarmonyOS 6.0 窗口管理与多窗口 📅 2026/7/22 4:10:46 窗口是HarmonyOS应用跟屏幕交互的基础单元——全屏、分屏、悬浮窗、亮度调节、屏幕常亮这些功能都挂在Window API上。用得好能大幅提升体验用得不好直接crash比如getMainWindowSync时机不对。获取窗口实例所有窗口操作的前提是拿到Window实例。推荐方式import{window}fromkit.ArkUI;// 在UIAbility的onWindowStageCreate中onWindowStageCreate(windowStage:window.WindowStage):void{windowStage.loadContent(pages/Index,(err){if(err.code){return;}// loadContent回调之后才能安全获取窗口letmainWindow:window.WindowwindowStage.getMainWindowSync();AppStorage.setOrCreatewindow.Window(mainWindow,mainWindow);});}关键getMainWindowSync()必须在loadContent回调之后调用。在loadContent之前调用会报1300002错误——这是新手最常犯的错。原因很简单loadContent之前窗口还没初始化完成取不到。另一种方式是在页面里通过UIAbilityContext获取import{window}fromkit.ArkUI;letmainWindow:window.Windowwindow.getLastWindow(this.context);getLastWindow是异步的返回Promise。同步方式只有getMainWindowSync但只能在WindowStage上用。全屏与沉浸式letmainWindow:window.WindowAppStorage.getwindow.Window(mainWindow);// 全屏布局(内容延伸到状态栏下方)mainWindow.setWindowLayoutFullScreen(true);// 获取避让区域letavoidArea:window.AvoidAreamainWindow.getAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);lettopHeight:numberavoidArea.visible?avoidArea.topRect.height:0;setWindowLayoutFullScreen(true)后内容会延伸到状态栏和导航栏区域但状态栏本身还是显示的。如果需要真正的全屏隐藏状态栏还要配合// 隐藏状态栏(需要SYSTEM_GRAPHIC_PERMISSION)mainWindow.setSpecificBarVisible(window.BarType.STATUS_BAR,false);大部分场景用setWindowLayoutFullScreen expandSafeArea就够了不需要隐藏状态栏。避让区域全屏布局后内容可能被状态栏/导航栏/键盘遮挡。getAvoidArea获取这些区域的信息// 系统避让(状态栏导航栏)letsystemAvoidArea:window.AvoidAreamainWindow.getAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);// 键盘避让letkeyboardAvoidArea:window.AvoidAreamainWindow.getAvoidArea(window.AvoidAreaType.TYPE_KEYBOARD);// 避让区域包含topRect和bottomRectlettopRect:window.RectsystemAvoidArea.topRect;// 状态栏区域letbottomRect:window.RectsystemAvoidArea.bottomRect;// 导航栏区域AvoidArea的visible字段表示该避让区是否可见。如果状态栏隐藏了visible为false。屏幕常亮阅读场景、视频播放需要保持屏幕不熄灭mainWindow.setWindowKeepScreenOn(true);// 开启常亮mainWindow.setWindowKeepScreenOn(false);// 关闭常亮setWindowKeepScreenOn是异步方法但不需要await。不需要额外权限。注意页面切到后台时常亮自动失效回到前台恢复。如果应用有后台保活需求要配BackgroundTaskManager。亮度调节// 设置屏幕亮度(0.0-1.0)mainWindow.setWindowBrightness(0.5);// 获取当前亮度letbrightness:numbermainWindow.getWindowBrightness();setWindowBrightness只影响当前窗口不影响系统亮度设置。适合阅读模式的亮度调节。坑不要把State变量命名为brightness——这个名字跟组件内置方法冲突会导致类型错误。用screenBrightness或其他名字。窗口类型HarmonyOS支持三种窗口类型类型说明场景WindowType.MAIN主窗口应用主界面WindowType.SUB子窗口弹窗、对话框WindowType.FLOAT浮动窗口悬浮窗、画中画创建子窗口letsubWindow:window.WindowmainWindow.createSubWindow(subWindow);subWindow.resize(300,400);subWindow.moveWindowTo(100,200);subWindow.showWindow();子窗口在主窗口内部位置和大小可控。适合自定义弹窗、浮层等。创建浮动窗口import{window}fromkit.ArkUI;letfloatWindow:window.Windowwindow.createWindow({name:floatWindow,windowType:window.WindowType.FLOAT,ctx:this.context});浮动窗口独立于主窗口可以在其他应用上方显示。需要ohos.permission.SYSTEM_FLOAT_WINDOW权限这是系统级权限普通应用难以获取。显示信息获取屏幕物理信息import{display}fromkit.ArkUI;letdefaultDisplay:display.Displaydisplay.getDefaultDisplaySync();letscreenWidth:numberdefaultDisplay.width;// 物理宽度(px)letscreenHeight:numberdefaultDisplay.height;// 物理高度(px)letdensity:numberdefaultDisplay.densityPixels;// 密度(如3.0)letrefreshRate:numberdefaultDisplay.refreshRate;// 刷新率letorientation:numberdefaultDisplay.orientation;// 方向densityPixels用于px→vp转换vp px / densityPixels。这个值在键盘高度计算等场景很有用。窗口生命周期UIAbility有五个跟窗口相关的回调exportdefaultclassEntryAbilityextendsUIAbility{onCreate():void{}// Ability创建onWindowStageCreate(windowStage):void{// 窗口创建 ← 在这里初始化onWindowStageDestroy(windowStage):void{// 窗口销毁onForeground():void{}// 前台onBackground():void{}// 后台}onWindowStageCreate是设置窗口属性的最佳时机。onForeground/onBackground可以用来暂停/恢复动画或定时器。窗口事件监听// 窗口大小变化mainWindow.on(windowSizeChange,(size:window.Size){// size.width, size.height});// 避让区域变化(如键盘弹出)mainWindow.on(avoidAreaChange,(data:window.AvoidAreaData){// data.type, data.area});// 可交互状态变化mainWindow.on(interactiveStatusChange,(interactive:boolean){// 窗口是否可交互});avoidAreaChange特别重要——键盘弹出时type为TYPE_KEYBOARD的避让区会变化通过这个回调可以精确计算键盘高度实现聊天输入框跟随。踩坑清单问题原因解决getMainWindowSync报1300002在loadContent之前调用移到loadContent回调后brightness变量报类型错误名字跟内置方法冲突改名screenBrightnessFLOAT窗口创建失败缺少权限声明SYSTEM_FLOAT_WINDOW全屏后内容被状态栏遮挡没处理避让区域expandSafeArea或getAvoidArea屏幕还是熄灭了应用到了后台配BackgroundTaskManagersetWindowBrightness无效参数范围0-1不是0-255用0.0-1.0范围子窗口不显示没调showWindow创建后调用showWindow()窗口管理的核心是时机——什么时候取实例、什么时候设属性、什么时候监听事件。搞清楚了loadContent后的时机要求和避让区域的计算逻辑窗口操作就不会出问题。