鸿蒙多端适配响应式断点解决方案
1获取屏幕尺寸,注册监听事件(entryability)
export default class EntryAbility extends UIAbility {
......
private windowObj?: window.Window
private curBp: string = ''
private updateBreakpoint(windowWidth: number) :void{
// 拿到当前窗口对象获取当前所在displayId
let displayId = this.windowObj?.getWindowProperties().displayId
// 将长度的单位由px换算为vp
let windowWidthVp = windowWidth / display.getDisplayByIdSync(displayId).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
// 使用状态变量记录当前断点值
AppStorage.setOrCreate('currentBreakpoint',
this.curBp)
}
}
.....
onWindowStageCreate(windowStage: window.WindowStage) :void{
// 注册监听窗口尺寸变化
windowStage.getMainWindow().then((windowObj) => {
this.windowObj = windowObj
// 获取应用启动时的窗口尺寸
this.updateBreakpoint(windowObj.getWindowProperties().windowRect.width)
// 注册回调函数,监听窗口尺寸变化
windowObj.on('windowSizeChange', (windowSize)=>{
this.updateBreakpoint(windowSize.width)
})
});
}
.....
}
封装一个基于断点判断的工具类
// 断点常量
export class BreakpointConstants {
// 手表等超小屏
static readonly XS: string = 'xs';
// 手机竖屏
static readonly SM: string = 'sm';
// 手机横屏,折叠屏
static readonly MD: string = 'md';
// 平板,2in1 设备
static readonly LG: string = 'lg';
// AppStorage 中的 key
static readonly BREAK_POINT_KEY: string = 'currentBreakpoint'
}
declare interface BreakPointTypeOption<T> {
xs?: T
sm?: T
md?: T
lg?: T
}
export class BreakPointType<T> {
options: BreakPointTypeOption<T>
constructor(option: BreakPointTypeOption<T>) {
this.options = option
}
// 根据断点取值
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 {
return undefined
}
}
}
3.使用
import { BreakpointConstants, BreakPointType } from '../model'
@Entry
@Component
struct test {
list: string[] = ['首页', '方向', '分享', '我的']
@StorageProp(BreakpointConstants.BREAK_POINT_KEY) breakPoint:string=''
build() {
Tabs() {
ForEach(this.list, (item: string, index) => {
TabContent() {
if (index == 0) {
this.testlist()
} else {
Text(item)
}
}.tabBar(this.breakPoint)
})
}.barPosition(BarPosition.Start)
.vertical(this.breakPoint === BreakpointConstants.LG ? true : false)
}
@Builder
testlist() {
Scroll(){
WaterFlow() {
ForEach(Array.from({ length: 20 }), (i: string) => {
FlowItem(){
Text()
.width('100%')
.height(300)
}.backgroundColor('#888')
})
//使用断点工具类就可以进行响应式布局
}.columnsTemplate(new BreakPointType<string>({
xs: '1fr',
sm: '1fr',
md: '1fr 1fr',
lg: '1fr 1fr 1fr '
}).getValue(this.breakPoint))
.rowsGap(10)
.columnsGap(10)
}
.width('100%')
.height('100%')
}
}
运行效果
平板端
折叠屏端
手机端
断点工具可以进行很多适配比如宽高也可以使用断点工具来对不同屏幕进行适配!