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

harmonyOS 手机,双折叠,平板,PC端屏幕适配

由于HarmonyOS设备的屏幕尺寸和分辨率各不相同,开发者需要采取适当的措施来适配不同的屏幕。

1.EntryAbility.ets文件里:onWindowStageCreate方法里判断设备类型,
如果是pad,需全屏展示(按客户需求来,本次需求按全屏展示),功能实现如下:

	onWindowStageCreate(windowStage: window.WindowStage): void {windowStage.getMainWindow().then((windowClass) => {try {//判断是否是padif(deviceInfo.deviceType == 'tablet') {//pad//pad横屏let orientation = window.Orientation.AUTO_ROTATION_LANDSCAPE_RESTRICTED;let promise = windowClass.setPreferredOrientation(orientation);//如果是pad横屏promise.then(() => {console.info('Succeeded in setting the window orientation.');}).catch((err: BusinessError) => {console.error(`Failed to set the window orientation. Cause code: ${err.code}, message: ${err.message}`);});}}catch (exception) {console.error(`Failed to set window orientation. Cause code: ${exception.code}, message: ${exception.message}`);}// 获取窗口尺寸,存入AppStorageAppStorage.setOrCreate('winWidth', windowClass.getWindowProperties().windowRect.width);AppStorage.setOrCreate('winHeight', windowClass.getWindowProperties().windowRect.height);// 监听窗口尺寸变化windowClass.on('windowSizeChange', (windowSize) => {//监听窗口尺寸变化AppStorage.setOrCreate('winWidth', windowSize.width);//如果窗口变化了,立马更新存储值-宽AppStorage.setOrCreate('winHeight', windowSize.height);//如果窗口变化了,立马更新存储值-高console.log('宽高',String(windowSize.width), String(windowSize.height))//});});// Main window is created, set main page for this abilityconsole.info('onWindowStageCreate');AppStorage.setOrCreate('windowStage',windowStage);AppUtil.init(this.context);try {let windowClass: window.Window = windowStage.getMainWindowSync()AppStorage.setOrCreate('windowClass', windowClass)// 设置窗口全屏windowClass.setWindowLayoutFullScreen(true)let topRect = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_CUTOUT).topRect//获取顶部安全区域let bottomRect = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRect//获取底部安全区域// 缓存window窗口对象AppStorage.setOrCreate('windowClass', windowClass);AppStorage.setOrCreate('bottomAreaRectHeight', bottomRect.height);//把height-底部安全区域存储AppStorage.setOrCreate('topAreaRectHeight', topRect.height );//height-顶部安全区域存储this.updateBreakPoint(windowClass.getWindowProperties().windowRect.width, windowClass.getWindowProperties().windowRect.height);//获取窗口的宽 度和高度,计算此时是什么场景:直板机、折叠屏、pad等windowClass.on('windowSizeChange', (windowSize: window.Size) => {console.log('windowSizeChange',windowSize.width, windowSize.height)this.updateBreakPoint(windowSize.width, windowSize.height);//})} catch (exception) {Logger.error(`Failed to obtain the main window. Cause code: ${exception.code}, message: ${exception.message}`);}windowStage.loadContent('pages/LaunchPage', (err, data) => { if (err.code) { Logger.error('Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); return; } }); }private updateBreakPoint(windowWidth: number, windowHeight: number): void {let curBp: string = '';let type = deviceInfo.deviceTypeif (type=='2in1'){//如果是电脑,直接走pad的适配(需要注意,如果是电脑,需要修改一些交互,比如键盘(onKeyEvent事件))AppStorage.setOrCreate('breakPoint', 'xl')return}// 平板,下面的就是根据当前实时屏幕尺寸,计算是处于哪种情况 md-直板机 lg-折叠屏  xl-pad(前面已提到,电脑的UI和pad的UI一致)if(type == 'tablet') {curBp = 'xl'AppStorage.setOrCreate('breakPoint', curBp)} else {console.log('windowHeight/windowWidth',windowWidth, windowHeight, windowHeight/windowWidth > 1.5)let windowWidthVp = windowWidth / display.getDefaultDisplaySync().densityPixels;if (windowWidthVp < 700) {curBp = 'md'} else {curBp = 'lg'}if(windowHeight/windowWidth > 1.5 == true) {curBp = 'md'} else {if(windowHeight<1500) {curBp = 'md'} else {curBp = 'lg'}}let ret: boolean = false;ret = display.isFoldable();console.log("curBp", curBp, windowWidthVp)if(deviceInfo.deviceType == 'phone' && ret == false) {AppStorage.setOrCreate('breakPoint', 'md')} else {AppStorage.setOrCreate('breakPoint', curBp)}}console.log('设备类型', curBp)}//以上的内容都是在应用入口完成,判断好设备类型和视口大小

2.上面是具体说明了判断设备的类型,以及监听窗口大小变化来更改视口类型,下面的内容主要是来介绍如何根据设备类型来适配UI:
其实在鸿蒙里,vp和安卓的dp单位等比,开发过程中,可以直接调成安卓单位的UI来开发,就可以兼容所有的设备(字体和组件宽高比,会自适应),我们需要关注的是,在不同设备下,布局的改变,这个时候需要根据我们计算出来的 breakPoint(xl:电脑,pad , lg:折叠屏 , md:手机)

export class BreakpointConstants{  //BreakpointConstants.ets工具类,md(直板机) lg(折叠屏) xl(电脑,平板)/*** Breakpoints that represent small device types.*/static readonly BREAKPOINT_SM: string = 'sm';/*** Breakpoints that represent middle device types.*/static readonly BREAKPOINT_MD: string = 'md';/*** Breakpoints that represent large device types.*/static readonly BREAKPOINT_LG: string = 'lg';/*** Breakpoints that represent large device types.*/static readonly BREAKPOINT_XL: string = 'xl';/*** Current breakpoints that to query the device types.*/static readonly CURRENT_BREAKPOINT: string = 'currentBreakpoint';/*** Range of the small device width.*/static readonly RANGE_SM: string = '(320vp<=width<520vp)';/*** Range of the middle device width.*/static readonly RANGE_MD: string = '(520vp<=width<840vp)';/*** Range of the large device width.*/static readonly RANGE_LG: string = '(840vp<=width)';/*** Range of the largePlus device width.*/static readonly RANGE_XL: string = '(1700vp<=width<=2720vp)';
}

使用方法如下:

 //声明一个变量,记录当前视口大小(md,lg,xl)(EntryAbility.ets存储值)@StorageLink('breakPoint') breakPoint: string = BreakpointConstants.BREAKPOINT_MD

布局兼容如下:

if (this.breakPoint=='xl') {  // pad 和 PC}else{  // 手机和双折叠}

双折叠适配如下:

①使用Flex布局

Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center, wrap: FlexWrap.Wrap }) {Column(){}.width(this.breakPoint == BreakpointConstants.BREAKPOINT_MD ? '100%' : '49%')Column(){}.width(this.breakPoint == BreakpointConstants.BREAKPOINT_MD ? '100%' : '49%')
}

②使用GridRow布局

 GridRow() {GridCol({ span: { sm: 12, md: 6, lg: 4 } }) {Column(){}}GridCol({ span: { sm: 12, md: 6, lg: 8 } }) {Column(){}}}.width('100%').height('100%')
http://www.xdnf.cn/news/3277.html

相关文章:

  • 数据隐私在Web3环境下的重要性及实现方法
  • Spring Boot集成Kafka并使用多个死信队列的完整示例
  • 【MySQL】增删改查(CRUD)
  • Microsoft Entra ID 免费版管理云资源详解
  • mysql-5.7.24-linux-glibc2.12-x86_64.tar.gz的下载安装和使用
  • 上海地区IDC机房服务器托管选型报告(2025年4月30日)
  • (51单片机)LCD显示红外遥控相关数据(Delay延时函数)(LCD1602教程)(Int0和Timer0外部中断教程)(IR红外遥控模块教程)
  • LeRobot 项目部署运行逻辑(三)——机器人及舵机配置
  • 【STM32实物】基于STM32的RFID多卡识别语音播报系统设计
  • 左右分屏电商带货视频批量混剪自动剪辑生产技术软件:智能剪辑与合规化方案解析
  • 【优选算法 | 前缀和】前缀和算法:高效解决区间求和问题的关键
  • 无侵入式的解决 ViewPager2 跟横向滑动子 View 手势冲突的一种思路
  • 人工智能数学基础(五):概率论
  • Kafka Producer的acks参数对消息可靠性有何影响?
  • 阿里云服务器技术纵览:从底层架构到行业赋能​
  • PostgreSQL数据库操作基本命令
  • JAVA SE 反射,枚举与lambda表达式
  • 制作一款打飞机游戏36:调度编辑器
  • K8S - 命名空间实战 - 从资源隔离到多环境管理
  • 系统升级姿势解锁:绞杀、并行与隐藏开关
  • 拥抱 Kotlin Flow
  • 虚幻商城 Quixel 免费资产自动化入库(2025年版)
  • ArcGIS Pro几个小知识点分享
  • WebRtc09:网络基础P2P/STUN/TURN/ICE
  • 「动态规划::背包」01背包 / AcWing 2(C++)
  • OpenCV 图形API(75)图像与通道拼接函数-----将 4 个单通道图像矩阵 (GMat) 合并为一个 4 通道的多通道图像矩阵函数merge4()
  • 章越科技赋能消防训练体征监测与安全保障,从传统模式到智能跃迁的实践探索
  • Hbuilder 开发鸿蒙应用,打包成 hap 格式(并没有上架应用商店,只安装调试用)
  • 【Vue2】4-开发者工具安装
  • HOW - 经典详情页表单内容数据填充(基于 Antd 组件库)