【鸿蒙实战开发】通过主窗口或媒体查询监听断点

199 篇文章 0 订阅
198 篇文章 0 订阅

断点

断点以应用宽度为切入点,将应用窗口在宽度维度分成几个不同的区间即不同的断点

在这里插入图片描述

开发者可以根据实际使用场景决定适配哪些断点。如xs断点对应的一般是智能穿戴类设备
可以根据实际需要在lg断点后面新增xl、xxl等断点。根据实际需要设置适配范围,避免增加较大程序的开发量

主窗口监听断点

1.断点更新方法

private updateBreakpoint(widowWidth: number) {
  // px换算为vp

  // 主窗口尺寸宽度:widowWidth
  // 设备逻辑像素的密度:display.getDefaultDisplaySync().densityPixels
  let windowWidthVp = widowWidth / display.getDefaultDisplaySync().densityPixels
  let newBp: string = ''
  if (windowWidthVp < 320) {
    newBp = 'xs'
  } else if (windowWidthVp < 600) {
    newBp = 'sm'
  } else if (windowWidthVp < 840) {
    newBp = 'md'
  } else {
    newBp = 'lg'
  }
  if (this.curBp !== newBp) {
    this.curBp = newBp
    promptAction.showToast({
      message: this.curBp
    })
    AppStorage.setOrCreate('currentBreakpoint', this.curBp)
  }
}

2.windowSizeChange监听主窗口尺寸变化

// 获取该WindowStage实例下的主窗口
const windowObj = await windowStage.getMainWindow()
// windowSizeChange 监听主窗口尺寸变化事件 返回窗口尺寸对象 {width,height}
windowObj.on('windowSizeChange', (widowSize) => {
  console.log(`widowSize`, JSON.stringify(widowSize));
  this.updateBreakpoint(widowSize.width)
})

媒体查询

1.媒体查询监听断点

import mediaQuery from '@ohos.mediaquery'

declare interface BreakPointTypeOption<T> {
  xs?: T
  sm?: T
  md?: T
  lg?: T
  xl?: T
  xxl?: T
}

// BreakPointType类接收断点参数option
export class BreakPointType<T> {
  options: BreakPointTypeOption<T>

  // 初始化参数option
  constructor(option: BreakPointTypeOption<T>) {
    this.options = option
  }

// 根据当前的断点,获取断点对应的options的参数值
  getValue(currentBreakPoint: string) {
    if (currentBreakPoint === 'xs') {
      return this.options.xs
    } else if (currentBreakPoint === 'sm') {
      return this.options.sm
    } else if (currentBreakPoint === 'md') {
      return this.options.md
    } else if (currentBreakPoint === 'lg') {
      return this.options.lg
    } else if (currentBreakPoint === 'xl') {
      return this.options.xl
    } else if (currentBreakPoint === 'xxl') {
      return this.options.xxl
    } else {
      return undefined
    }
  }
}

interface Breakpoint {
  name: string
  size: number
  mediaQueryListener?: mediaQuery.MediaQueryListener
}

// 断点工具-BreakpointSystem类
export class BreakpointSystem {
  private currentBreakpoint: string = 'md'
  private breakpoints: Breakpoint[] = [
    { name: 'xs', size: 0 }, // 0 ~ 320
    { name: 'sm', size: 320 }, // 320 ~ 600
    { name: 'md', size: 600 }, // 600 ~ 840
    { name: 'lg', size: 840 },// 840 ~
  ]

  // 注册断点
  public register() {
    this.breakpoints.forEach((breakpoint: Breakpoint, index) => {
    
      // 设置媒体查询的查询条件
      let condition: string
      if (index === this.breakpoints.length - 1) {
        condition = `(${breakpoint.size}vp<=width)`
      } else {
     condition = `(${breakpoint.size}vp<=width<${this.breakpoints[index + 1].size}vp)`
      }
      
      // MediaQueryListener-查询条件对应的监听句柄
      breakpoint.mediaQueryListener = mediaQuery.matchMediaSync(condition)
      
      // 通过句柄向对应的查询条件注册回调,当媒体属性发生变更时会触发该回调
      breakpoint.mediaQueryListener.on('change', (mediaQueryResult) => {
      
      // matches-条件信息与系统信息相比较,未初始化时,返回false
        if (mediaQueryResult.matches === true) {
          this.updateCurrentBreakpoint(breakpoint.name)
        }
      })
    })
  }

  // 取消注册
  public unregister() {
    this.breakpoints.forEach((breakpoint: Breakpoint) => {
      if (breakpoint.mediaQueryListener) {
        breakpoint.mediaQueryListener.off('change')
      }
    })
  }

  // 更新断点信息
  private updateCurrentBreakpoint(breakpoint: string) {
    if (this.currentBreakpoint !== breakpoint) {
      this.currentBreakpoint = breakpoint
      AppStorage.set<string>('currentBreakpoint', this.currentBreakpoint)
    }
  }
}

2.页面中的具体使用

breakpointSys:BreakpointSystem=new BreakpointSystem()
@StorageProp('currentBreakpoint') currentBreakpint:string=''

aboutToAppear():void{
    this.breakpointSys.register()
}
aboutToAppear():void{
    this.breakpointSys.unregister()
}


Grid(){
    GridItem(){}...
}
.columnsTemplate(
new BreakPointType({
    sm:'1fr '.repeat(2),
    md:'1fr '.repeat(4),
    lg:'1fr '.repeat(6)
}).getValue(this.currentBreakpoint)
)

写在最后

●如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
●点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
●关注小编,同时可以期待后续文章ing ,不定期分享原创知识。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值