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

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

1.EntryAbility.ets文件里:onWindowStageCreate方法里判断设备类型,

如果是pad,需全屏展示(按客户需求来,本次需求按全屏展示),功能实现如下:

复制代码
	onWindowStageCreate(windowStage: window.WindowStage): void {
	  windowStage.getMainWindow().then((windowClass) => {
	    try {
	      //判断是否是pad
	      if(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}`);
	    }
	    // 获取窗口尺寸,存入AppStorage
	    AppStorage.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 ability
	  console.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.deviceType
	  if (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%')
相关推荐
特立独行的猫a6 小时前
HarmonyOS NEXT 诗词元服务项目开发上架全流程实战(二、元服务与应用APP签名打包步骤详解)
华为·打包发布·harmonyos·应用签名·appgallery
QuartusII77 小时前
如何禁止AutoCAD这类软件联网
运维·windows·电脑
桦08 小时前
误触网络重置,笔记本电脑wifi连接不上解决方法(Win10,Win11通用)
网络·电脑
周胡杰9 小时前
鸿蒙文件上传-从前端到后端详解,对比jq请求和鸿蒙arkts请求区别,对比new FormData()和鸿蒙arktsrequest.uploadFile
前端·华为·harmonyos·鸿蒙·鸿蒙系统
qq_5260991315 小时前
PLC与工业电脑:有什么区别?
服务器·电脑·负载均衡
bestadc1 天前
入门版 鸿蒙 组件导航 (Navigation)
harmonyos
HarmonyOS_SDK1 天前
几行代码配置高频按钮,保障用户体验一致
harmonyos
众乐 认证1 天前
百度CarLife实现手机车机无缝互联
智能手机·carlife·车机互联
松间听雨1 天前
开源免费 PDF 编辑器来了,付费软件平替!
经验分享·pdf·电脑·软件需求