一、背景
在渲染页面时,需要根据不同屏幕大小渲染出不同的效果,动态的判断设备屏幕大小,便需要采用多设备响应式布局。这种设计方法能够动态适配各种屏幕大小,确保网站在不同设备上都能呈现出最佳的效果。
二、媒体查询(mediaquery)
媒体查询作为响应式设计的核心,在移动设备上应用十分广泛。媒体查询可根据不同设备类型或同设备不同状态修改应用的样式。媒体查询常用于下面两种场景:
- 针对设备和应用的属性信息(比如显示区域、深浅色、分辨率),设计出相匹配的布局。
- 当屏幕发生动态改变时(比如分屏、横竖屏切换),同步更新应用的页面布局。
2.1、引入与使用流程
设备状态 | 媒体查询条件 |
SM | (320vp<=width<600vp) |
MD | (600vp<=width<840vp) |
LG | (840vp<=width) |
①导入媒体查询模块
import mediaquery from '@ohos.mediaquery';
②设置媒体查询条件,并获取对应的listener
let listener = mediaquery.matchMediaSync('(320vp<=width<600vp)');
③给listener设置回调函数,当设备状态变化时会执行回调函数
//设置监听回调函数
listener.on('change',result => {
//判断是否满足媒体查询条件
if(result.matches){
//记录当前设备状态
}
})
④将设备状态记录到全局状态中
AppStorage.SetOrCreate('currentBreakpoint','SM')
@StorageProp('currentBreakpoint') currentBreakpoint:string = 'SM'
2.2、具体实现
2.2.1、案例说明
⭐背景情况:在渲染页面时,不同屏幕大小渲染出效果是一样的,tabs都是在底部
⭐期望:根据不同屏幕大小渲染出不同的效果,tabs动态展示
2.2.2、实现步骤
①定义不同大小屏幕设备的Breakpoints 标记文件
import BreakpointType from '../bean/BreanpointType';
export default class BreakpointConstants {
/**
* 小屏幕设备的 Breakpoints 标记.
*/
static readonly BREAKPOINT_SM: string = 'sm';
/**
* 中等屏幕设备的 Breakpoints 标记.
*/
static readonly BREAKPOINT_MD: string = 'md';
/**
* 大屏幕设备的 Breakpoints 标记.
*/
static readonly BREAKPOINT_LG: string = 'lg';
/**
* 当前设备的 breakpoints 存储key
*/
static readonly CURRENT_BREAKPOINT: string = 'currentBreakpoint';
/**
* 小屏幕设备宽度范围.
*/
static readonly RANGE_SM: string = '(320vp<=width<600vp)';
/**
* 中屏幕设备宽度范围.
*/
static readonly RANGE_MD: string = '(600vp<=width<840vp)';
/**
* 大屏幕设备宽度范围.
*/
static readonly RANGE_LG: string = '(840vp<=width)';
static readonly BAR_POSITION: BreakpointType<BarPosition> = new BreakpointType({
sm: BarPosition.End,
md: BarPosition.Start,
lg: BarPosition.Start,
})
}
②定义媒体查询工具类,用来完成监听器的自定义和使用,并将监听器进行存储
import mediaQuery from '@ohos.mediaquery';
import BreakpointConstants from '../constants/BreakpointConstants'
export default class BreakpointSystem{
//定义3个屏幕监听器
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)
//定义回调函数
smListenerCallback(result: mediaQuery.MediaQueryResult){
if(result.matches){
this.updateCurrentBreakpoint(BreakpointConstants.BREAKPOINT_SM)
}
}
mdListenerCallback(result: mediaQuery.MediaQueryResult){
if(result.matches){
this.updateCurrentBreakpoint(BreakpointConstants.BREAKPOINT_MD)
}
}
lgListenerCallback(result: mediaQuery.MediaQueryResult){
if(result.matches){
this.updateCurrentBreakpoint(BreakpointConstants.BREAKPOINT_LG)
}
}
//定义存储函数,以上3个函数中调用
updateCurrentBreakpoint(breakpoint: string){
AppStorage.SetOrCreate(BreakpointConstants.CURRENT_BREAKPOINT, breakpoint)
}
//监听
register(){
this.smListener.on('change', this.smListenerCallback.bind(this))
this.mdListener.on('change', this.mdListenerCallback.bind(this))
this.lgListener.on('change', this.lgListenerCallback.bind(this))
}
//取消监听
unregister(){
this.smListener.off('change', this.smListenerCallback.bind(this))
this.mdListener.off('change', this.mdListenerCallback.bind(this))
this.lgListener.off('change', this.lgListenerCallback.bind(this))
}
}
/*
* 1、定义3个屏幕监听器
* 2、分别监听不同的屏幕获取宽度范围
* (先定义3个屏幕的函数,定义函数时使用AppStorage进行存储)+(再进行绑定,利用on监听,off取消监听)
* */
③定义标记类型,页面中使用
//定义标记类型
declare interface BreakpointTypeOptions<T>{
sm?:T,
md?:T,
lg?:T
}
export default class BreakpointType<T>{
options: BreakpointTypeOptions<T>
constructor(options: BreakpointTypeOptions<T>) {
this.options = options
}
getValue(breakpoint: string): T{
return this.options[breakpoint]
}
}
④在页面中使用,不同屏幕展示不同大小
说明:在首页中使用breakpointSystem完成初始化在当前组件构建之前,去调用,完成注册;在组件销毁时,完成取消注册
tabs根据不同屏幕大小来显示方向位置