当前位置: 首页 > news >正文

鸿蒙刘海屏、水滴屏、瀑布屏适配:用 DisplayUtil 获取不可用区域

文章目录

    • 一、前言
    • 二、工具函数方法
    • 三、方法详解
      • 3.1 `getCutoutRect()` — 获取不可用区域矩形
      • 3.2 `getCutoutHeight()` — 获取挖孔区域高度
    • 四、完整演示代码
      • 4.1 数据加载
      • 4.2 UI 渲染
    • 五、实际应用场景
      • 场景 1:计算顶部安全内边距
      • 场景 2:判断是否全面屏并调整布局
      • 场景 3:获取完整矩形信息用于精确避让
    • 六、注意事项
    • 七、小结

一、前言

近期发现一款很有意思的HarmonyOS 三方库, 地址 @pura/harmony-utils(V1.4.0) , 作者是"桃花镇童长老", 我这里也是直接通过该作者公布的源码进行案例编写进行,写了到目前写了一部分demo ,感觉确实很有帮助,这里呢也是开始写一个系列的演示demo 供大家参考。如有帮助可以在OpenHarmony中进行下载安装进行使用哦

案例demo导航展示

↓↓↓↓↓↓接下来言归正传 ↓↓↓↓

现代手机大多采用异形屏设计:刘海屏、水滴屏、挖孔屏、瀑布屏……这些屏幕在顶部或边角存在不可用区域(即摄像头挖孔区域),如果应用内容出现在这些区域,就会被摄像头遮挡,影响用户体验。

HarmonyOS 提供了display.getCutoutInfo()API 来获取这些不可用区域的坐标信息,DisplayUtil对其进行了二次封装,提供了更简洁的getCutoutRect()getCutoutHeight()方法。


二、工具函数方法

// 获取挖孔/刘海区域的矩形坐标(异步)staticasyncgetCutoutRect():Promise<display.Rect>// 获取挖孔/刘海区域的高度(px,异步)staticasyncgetCutoutHeight():Promise<number>

三、方法详解

3.1getCutoutRect()— 获取不可用区域矩形

源码:

staticasyncgetCutoutRect():Promise<display.Rect>{letcutoutInfo=awaitDisplayUtil.getDefaultDisplaySync().getCutoutInfo();returncutoutInfo.boundingRects[0];}

说明:

  • getCutoutInfo()返回的是完整的CutoutInfo对象,包含boundingRects(不可用区域矩形数组)。
  • DisplayUtil取数组第一个元素(boundingRects[0]),即主挖孔区域。
  • 返回的display.Rect对象包含:
    • left:矩形左边距(px)
    • top:矩形上边距(px)
    • width:矩形宽度(px)
    • height:矩形高度(px)

如果设备没有挖孔(全面屏)boundingRects可能为空,boundingRects[0]返回undefined,Demo 中对此有判断处理。


3.2getCutoutHeight()— 获取挖孔区域高度

源码:

staticasyncgetCutoutHeight():Promise<number>{letrect=awaitDisplayUtil.getCutoutRect();if(rect){returnrect.height;}return0;}

说明:

  • 如果有挖孔区域,返回该区域的高度(px)。
  • 如果没有挖孔区域(全面屏),返回0

这个方法非常实用:在计算顶部布局安全区域时,直接用挖孔高度来做内边距偏移即可。


四、完整演示代码

4.1 数据加载

loadCutoutInfo(){this.cutoutLoading=true;DisplayUtil.getCutoutRect().then((rect)=>{this.cutoutLoading=false;if(rect){this.cutoutRectInfo=`left:${rect.left}, top:${rect.top}, width:${rect.width}, height:${rect.height}`;this.addLog('Cutout',`getCutoutRect() OK -${this.cutoutRectInfo}`,'success');}else{this.cutoutRectInfo='无挖孔/刘海区域(全面屏)';this.addLog('Cutout','getCutoutRect() - 无挖孔区域','info');}}).catch((e:Error)=>{this.cutoutLoading=false;this.cutoutRectInfo=`获取失败:${e.message}`;this.addLog('Cutout',`getCutoutRect() 失败:${e.message}`,'error');});DisplayUtil.getCutoutHeight().then((h)=>{this.cutoutHeightInfo=h>0?`${h}px`:'无';this.addLog('Cutout',`getCutoutHeight() =${h}px`,'info');}).catch((e:Error)=>{this.cutoutHeightInfo=`失败:${e.message}`;});}

4.2 UI 渲染

// ══ 挖孔屏 ════════════════════════════════════════if(this.activeTab===2){Column(){Text('getCutoutRect() - 获取挖孔屏区域').fontSize(13).fontColor('#666').fontWeight(FontWeight.Medium).alignSelf(ItemAlign.Start).margin({bottom:8})Row(){Text('区域信息:').fontSize(12).fontColor('#888')if(this.cutoutLoading){LoadingProgress().width(16).height(16).margin({left:6})Text('加载中...').fontSize(12).fontColor('#888').margin({left:4})}else{Text(this.cutoutRectInfo||'无').fontSize(12).fontFamily('monospace').fontColor('#4080FF').margin({left:6})}}.width('100%').margin({bottom:8})Row(){Text('挖孔高度:').fontSize(12).fontColor('#888')Text(this.cutoutHeightInfo||'--').fontSize(12).fontWeight(FontWeight.Bold).fontColor('#D63384').margin({left:6})}.width('100%').margin({bottom:10})Row(){Text('💡 ').fontSize(12).fontColor('#FF9800')Text('挖孔区域用于规避刘海/水滴/瀑布屏不可用区域,确保内容不被遮挡').fontSize(11).fontColor('#888')}.width('100%').backgroundColor('#FFF7E6').padding(8).borderRadius(6).margin({bottom:10})Button('刷新挖孔信息').fontSize(12).height(34).backgroundColor('#4080FF').fontColor('#FFF').onClick(()=>{this.loadCutoutInfo();})}.width('100%').padding(14).backgroundColor('#FFFFFF').borderRadius(12)this.buildApiCard('Cutout API',[{name:'getCutoutRect()',desc:'异步获取第一个挖孔/刘海区域 rect(left/top/width/height)'},{name:'getCutoutHeight()',desc:'异步获取挖孔区域高度(px),无挖孔返回 0'},]asApiRow[])}

五、实际应用场景

场景 1:计算顶部安全内边距

// 在页面初始化时获取挖孔高度,用于计算顶部安全区域asyncaboutToAppear(){constcutoutHeight=awaitDisplayUtil.getCutoutHeight();// 加上系统状态栏高度,得到真正的安全顶部内边距this.safeTopPadding=cutoutHeight;}

场景 2:判断是否全面屏并调整布局

asynccheckFullScreen(){constheight=awaitDisplayUtil.getCutoutHeight();if(height===0){// 全面屏,顶部内容可以贴边this.topInset=0;}else{// 异形屏,需要避让挖孔区域this.topInset=height;}}

场景 3:获取完整矩形信息用于精确避让

asyncavoidCutout(){constrect=awaitDisplayUtil.getCutoutRect();if(rect){// 挖孔在顶部中央,宽度为 rect.width,高度为 rect.height// 可以用于计算内容左右边距,确保重要内容不出现在挖孔区域constsafeLeft=rect.left;constsafeRight=DisplayUtil.getWidth()-rect.left-rect.width;console.info(`安全左边距:${safeLeft}px, 安全右边距:${safeRight}px`);}}

六、注意事项

  1. 全面屏处理:无挖孔的全面屏设备,getCutoutRect()返回的数组可能为空,需要判断rect是否为undefined

  2. 单位为物理像素(px):获取的矩形坐标是物理像素,在 ArkUI 中使用时需要转换为 vp(vp = px / densityPixels)。

  3. 异步方法:两个方法都是异步的(Promise),需要在aboutToAppearasync函数中await,或使用.then().catch()

  4. 多个挖孔区域boundingRects是数组,某些设备可能有多个挖孔区域(如顶部+底部)。DisplayUtil只取了[0],若需要处理所有区域,需要直接调用display.getCutoutInfo()


七、小结

方法返回类型说明
getCutoutRect()Promise<display.Rect>挖孔区域矩形(left/top/width/height),全面屏返回 undefined
getCutoutHeight()Promise<number>挖孔区域高度(px),全面屏返回 0

这两个方法是实现全面屏适配的关键。只需一行await DisplayUtil.getCutoutHeight(),就能在所有类型的屏幕上正确规避不可用区域,让你的应用在各种异形屏上都能完美呈现。

http://www.jsqmd.com/news/900904/

相关文章:

  • 从PC到AI,联想中国一场必打的仗
  • 如何快速上手AdelaiDepth:5分钟实现单目深度估计 [特殊字符]
  • HarmonyOS FoldStatus 与 FoldDisplayMode 枚举深度解析:折叠屏开发不再难
  • 多家对比才知道!机闸一体式钢制闸门哪家好、哪家优惠?认准河北闸之都实体厂家,可定制,品质价格双保障 - 栗子测评
  • 10个免费VMware Workstation Pro 17许可证密钥:专业虚拟化快速激活指南
  • LightRAG 入门指南:手把手教你用图增强 RAG 系统
  • 别再死记硬背了!用COMSOL做场路耦合,搞懂‘外部U vs. I’和‘外部I vs. U’到底怎么选
  • 2026年移动岗亭十大品牌厂家推荐:不锈钢/铝合金/雕花板岗亭,小区/工地/景区/警务/收费多场景定制选购指南 - 品牌企业推荐师(官方)
  • 从理论到实践:MiniCPM5-1B-MLX架构设计与实现原理深度剖析
  • 智能体时代,AI支付会是下一个“二维码”吗?
  • Bat批处理进阶玩法:用ren命令批量重命名,实现‘去头掐尾’和‘中间替换’
  • 2026年 EPS/EPP源头厂家最新推荐榜:东莞EPS颗粒、阻燃EPS板材、EPP保温箱及EPP托盘与周转箱专业实力深度解析 - 品牌企业推荐师(官方)
  • R语言偏相关分析实战:用ppcor包和自定义函数搞定土壤微生物数据
  • SY_AICC/gpt2安全与伦理:如何规避生成文本中的偏见与风险
  • 避坑指南:TextMeshPro打字机效果实现时,为什么你的字符淡入会‘穿帮’?
  • AURIX TC397内存不够用?三种方法教你手动指定变量到PSRR、DSRR等地址空间
  • 2026年口碑好的山东防坠落安全绳/高空作业安全绳厂家推荐与选型指南 - 品牌宣传支持者
  • 终极FPDF指南:5分钟学会用纯PHP生成专业PDF文档
  • 数字隔离器的用途和技术指标有哪些
  • 江西不锈钢水表箱怎么选?认准源头工厂!江西泗方水处理是专业批发厂家,可定制加工,靠谱厂家推荐看这里 - 栗子测评
  • 基于Python的数据画像解析工具:从平台数据到个人数字画像
  • 面试高频:Spring AI 统一聊天入口怎么设计,这次把路由和降级讲具体
  • PowerDesigner画UML图总是不好看?这5个隐藏的样式配置技巧(含箭头文字显示修复)
  • 2026年 饰品回收推荐榜单:东莞卡地亚/梵克雅宝/宝格丽/蒂芙尼/香奈儿等大牌饰品高价上门回收与专业收购指南 - 品牌企业推荐师(官方)
  • 临沂批发必看!旭阳电器商行精选扬子骆驼、熊猫、米小可电风扇,冷风机、商务扇优质货源,本地靠谱供货商一站式推荐 - 栗子测评
  • 首次使用 Taotoken 从注册到发出第一个 API 请求的全记录
  • 账单不是因为模型贵,而是因为请求长歪了:我怎么排查 token 成本
  • Linux基础开发工具集合
  • 工程采购发愁?找不到合适机闸一体式钢制、铸铁闸门厂家?河北闸之都实体工厂,可定做,物美价廉质量过硬 - 栗子测评
  • nli-roberta-base开发者进阶:如何基于该模型构建复杂的多模态推理系统