news 2026/7/20 12:27:11

HarmonyOS 6.0 窗口管理与多窗口

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HarmonyOS 6.0 窗口管理与多窗口

窗口是HarmonyOS应用跟屏幕交互的基础单元——全屏、分屏、悬浮窗、亮度调节、屏幕常亮,这些功能都挂在Window API上。用得好能大幅提升体验,用得不好直接crash(比如getMainWindowSync时机不对)。

获取窗口实例

所有窗口操作的前提是拿到Window实例。推荐方式:

import{window}from'@kit.ArkUI';// 在UIAbility的onWindowStageCreate中onWindowStageCreate(windowStage:window.WindowStage):void{windowStage.loadContent('pages/Index',(err)=>{if(err.code){return;}// loadContent回调之后才能安全获取窗口letmainWindow:window.Window=windowStage.getMainWindowSync();AppStorage.setOrCreate<window.Window>('mainWindow',mainWindow);});}

关键:getMainWindowSync()必须在loadContent回调之后调用。在loadContent之前调用会报1300002错误——这是新手最常犯的错。原因很简单:loadContent之前窗口还没初始化完成,取不到。

另一种方式是在页面里通过UIAbilityContext获取:

import{window}from'@kit.ArkUI';letmainWindow:window.Window=window.getLastWindow(this.context);

getLastWindow是异步的,返回Promise。同步方式只有getMainWindowSync,但只能在WindowStage上用。

全屏与沉浸式

letmainWindow:window.Window=AppStorage.get<window.Window>('mainWindow');// 全屏布局(内容延伸到状态栏下方)mainWindow.setWindowLayoutFullScreen(true);// 获取避让区域letavoidArea:window.AvoidArea=mainWindow.getAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);lettopHeight:number=avoidArea.visible?avoidArea.topRect.height:0;

setWindowLayoutFullScreen(true)后内容会延伸到状态栏和导航栏区域,但状态栏本身还是显示的。如果需要真正的全屏(隐藏状态栏),还要配合:

// 隐藏状态栏(需要SYSTEM_GRAPHIC_PERMISSION)mainWindow.setSpecificBarVisible(window.BarType.STATUS_BAR,false);

大部分场景用setWindowLayoutFullScreen + expandSafeArea就够了,不需要隐藏状态栏。

避让区域

全屏布局后,内容可能被状态栏/导航栏/键盘遮挡。getAvoidArea获取这些区域的信息:

// 系统避让(状态栏+导航栏)letsystemAvoidArea:window.AvoidArea=mainWindow.getAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);// 键盘避让letkeyboardAvoidArea:window.AvoidArea=mainWindow.getAvoidArea(window.AvoidAreaType.TYPE_KEYBOARD);// 避让区域包含topRect和bottomRectlettopRect:window.Rect=systemAvoidArea.topRect;// 状态栏区域letbottomRect:window.Rect=systemAvoidArea.bottomRect;// 导航栏区域

AvoidArea的visible字段表示该避让区是否可见。如果状态栏隐藏了,visible为false。

屏幕常亮

阅读场景、视频播放需要保持屏幕不熄灭:

mainWindow.setWindowKeepScreenOn(true);// 开启常亮mainWindow.setWindowKeepScreenOn(false);// 关闭常亮

setWindowKeepScreenOn是异步方法但不需要await。不需要额外权限。

注意:页面切到后台时常亮自动失效,回到前台恢复。如果应用有后台保活需求,要配BackgroundTaskManager。

亮度调节

// 设置屏幕亮度(0.0-1.0)mainWindow.setWindowBrightness(0.5);// 获取当前亮度letbrightness:number=mainWindow.getWindowBrightness();

setWindowBrightness只影响当前窗口,不影响系统亮度设置。适合阅读模式的亮度调节。

坑:不要把@State变量命名为brightness——这个名字跟组件内置方法冲突,会导致类型错误。用screenBrightness或其他名字。

窗口类型

HarmonyOS支持三种窗口类型:

类型说明场景
WindowType.MAIN主窗口应用主界面
WindowType.SUB子窗口弹窗、对话框
WindowType.FLOAT浮动窗口悬浮窗、画中画

创建子窗口

letsubWindow:window.Window=mainWindow.createSubWindow('subWindow');subWindow.resize(300,400);subWindow.moveWindowTo(100,200);subWindow.showWindow();

子窗口在主窗口内部,位置和大小可控。适合自定义弹窗、浮层等。

创建浮动窗口

import{window}from'@kit.ArkUI';letfloatWindow:window.Window=window.createWindow({name:'floatWindow',windowType:window.WindowType.FLOAT,ctx:this.context});

浮动窗口独立于主窗口,可以在其他应用上方显示。需要ohos.permission.SYSTEM_FLOAT_WINDOW权限,这是系统级权限,普通应用难以获取。

显示信息

获取屏幕物理信息:

import{display}from'@kit.ArkUI';letdefaultDisplay:display.Display=display.getDefaultDisplaySync();letscreenWidth:number=defaultDisplay.width;// 物理宽度(px)letscreenHeight:number=defaultDisplay.height;// 物理高度(px)letdensity:number=defaultDisplay.densityPixels;// 密度(如3.0)letrefreshRate:number=defaultDisplay.refreshRate;// 刷新率letorientation:number=defaultDisplay.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变量报类型错误名字跟内置方法冲突改名screenBrightness
FLOAT窗口创建失败缺少权限声明SYSTEM_FLOAT_WINDOW
全屏后内容被状态栏遮挡没处理避让区域expandSafeArea或getAvoidArea
屏幕还是熄灭了应用到了后台配BackgroundTaskManager
setWindowBrightness无效参数范围0-1不是0-255用0.0-1.0范围
子窗口不显示没调showWindow创建后调用showWindow()

窗口管理的核心是"时机"——什么时候取实例、什么时候设属性、什么时候监听事件。搞清楚了loadContent后的时机要求和避让区域的计算逻辑,窗口操作就不会出问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/20 12:27:02

HarmonyOS 6.0 录音开发——从采集到文件

录音在HarmonyOS里分两层&#xff1a;底层的AudioCapturer直接操作PCM数据&#xff0c;上层的media.createSoundPool做短音效。语音消息、会议记录用AudioCapturer&#xff0c;按钮点击音效用SoundPool。这篇把两条线都走通。权限 录音需要MICROPHONE权限&#xff1a; // modul…

作者头像 李华
网站建设 2026/7/20 12:25:55

GPT-5.6 更聪明之外:模型竞争开始算成本账

GPT-5.6 把模型升级拉回成本、稳定性和拒答边界。 从每 token 更多智能到模糊输入拒答&#xff0c;开发者该重新评估模型真实稳定性。大模型发布会越来越像一场账本公开。 过去大家盯着模型参数、上下文长度和榜单名次。现在真正敏感的问题变成了&#xff1a;同样一美元、同样一…

作者头像 李华
网站建设 2026/7/20 12:25:53

影刀RPA 流程审计日志:谁在什么时候做了什么

影刀RPA 流程审计日志&#xff1a;谁在什么时候做了什么 作者&#xff1a;林焱 什么情况用 流程跑着跑着出了问题&#xff0c;你要排查&#xff0c;发现——不知道哪一步出的错、不知道什么时间跑的、不知道输入是什么。只能从头到尾加断点重跑一遍&#xff0c;整个过程像在抓…

作者头像 李华
网站建设 2026/7/20 12:25:49

C++手把手解析OBJ文件:从格式原理到MeshLab可视化验证

1. 项目概述与核心价值 最近在整理一些三维模型处理的老项目&#xff0c;发现很多朋友对如何从最原始的模型文件格式入手&#xff0c;理解三维数据的底层结构很感兴趣。尤其是OBJ这种“古老”但生命力顽强的格式&#xff0c;它就像三维世界的“TXT”文件&#xff0c;结构清晰&…

作者头像 李华
网站建设 2026/7/20 12:25:33

2023任天堂夏季直面会:28款游戏发售日期与亮点解析

1. 任天堂直面会2023夏季游戏阵容全解析北京时间6月21日晚&#xff0c;任天堂举办了2023年度夏季直面会&#xff08;Nintendo Direct&#xff09;&#xff0c;这场时长40分钟的发布会堪称近年来内容最密集的一次。作为从业15年的游戏媒体人&#xff0c;我完整梳理了本次公布的2…

作者头像 李华