鸿蒙之折叠屏适配

时间:2024-11-20 12:12:02

在华为手机中,有两折叠也有三折叠,不同的折叠方式有不同的样式。以及在鸿蒙生态下提出的技术理念:一次开发,多端部署,所以不同屏幕大小的适配就是比较重要的了。

方式一:GridRow、GridCol栅格布局

通过将页面划分为等宽的列数和行数,可以方便地对页面元素进行定位和排版。 根据屏幕断点动态改变行数或者列数。

代码如下:

.onBreakpointChange((breakpoint) => {
  switch (breakpoint) {
    case 'md':
      this.showMaximum = 7;
      break;
    case 'lg':
    case 'xl':
    case 'xxl':
      this.showMaximum = 9;
      break;
    default:
    // xs、sm
      this.showMaximum = 4;
      break;
  }

方式二:displayBreakPointUtil工具类

引入断点值后,使用displayBreakPointUtil工具类传入三个枚举值,响应式获取相应的值。 代码如下:

export class BreakPointSystem {
  private currentBreakPoint: string = BreakPointConstants.BREAKPOINT_SM
  private smListener: mediaquery.MediaQueryListener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_SM)
  private mdListener: mediaquery.MediaQueryListener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_MD);
  private lgListener: mediaquery.MediaQueryListener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_LG);

  private updateCurrentBreakPoint(breakPoint: string): void {
    if (this.currentBreakPoint !== breakPoint) {
      this.currentBreakPoint = breakPoint;
      AppStorage.setOrCreate<string>(StorageFoldDisplayConstants.CURRENT_BREAKPOINT, this.currentBreakPoint)
    }
  }

  private isBreakPointSM = (mediaqueryResult: mediaquery.MediaQueryResult): void => {
    if (mediaqueryResult.matches) {
      this.updateCurrentBreakPoint(BreakPointConstants.BREAKPOINT_SM);
    }
  }
  private isBreakPointMD = (mediaQueryResult: mediaquery.MediaQueryResult): void => {
    if (mediaQueryResult.matches) {
      this.updateCurrentBreakPoint(BreakPointConstants.BREAKPOINT_MD);
    }
  }
  private isBreakPointLG = (mediaQueryResult: mediaquery.MediaQueryResult): void => {
    if (mediaQueryResult.matches) {
      this.updateCurrentBreakPoint(BreakPointConstants.BREAKPOINT_LG);
    }
  }

  //注册监听函数
  public register(): void {
    this.smListener.on('change', this.isBreakPointSM);
    this.mdListener.on('change', this.isBreakPointMD);
    this.lgListener.on('change', this.isBreakPointLG);
    //注册监听时当前状态不会产生回调,需要手动判断一下
      this.updateCurrentBreakPoint(getCurrentBreakPoint());
  }
  //注销监听函数
  public unregister(): void {
    this.smListener.off('change', this.isBreakPointSM);
    this.mdListener.off('change', this.isBreakPointMD);
    this.lgListener.off('change', this.isBreakPointLG);
  }
}

方式三:foldStatusChangeListeners工具类

内部封装了对'foldStatusChange'的事件的注册、注销,当屏幕断点发生改变后收到回调。 代码如下:

/**
 * 开启折叠设备折叠状态变化的监听。
 * @param callback
 */
public static onDisplayFolding(callback: Callback<display.FoldStatus>) {
  try {
    display.on('foldStatusChange', callback);
  } catch (exception) {
    console.error('Failed to register callback. Code: ' + JSON.stringify(exception));
  }
}

/**
 * 关闭折叠设备折叠状态变化的监听。
 * @param callback 若没有参数则取消所有监听
 */
public static offDisplayFolding(callback?: Callback<display.FoldStatus>) {
  try {
    display.off('foldStatusChange', callback);
  } catch (exception) {
    console.error('Failed to register callback. Code: ' + JSON.stringify(exception));
  }
}

使用:

// 使用
 let callback: Callback<display.FoldStatus> = (data: display.FoldStatus) => {
   console.info('Listening enabled. Data: ' + JSON.stringify(data));
 };
foldStatusChangeListeners.onDisplayFolding(callback)

注意:

foldStatusChange事件是折叠完成之前收到回调,在foldStatusChange事件中获取屏幕大小,获取到的还是之前的大小,而'foldDisplayModeChange'事件是在折叠之后收到回调,使用时需要注意。