HarmonyOS 鸿蒙Next 媒体查询中,折叠屏手机折叠起来,监听器监听不到
HarmonyOS 鸿蒙Next 媒体查询中,折叠屏手机折叠起来,监听器监听不到 对于这个媒体查询的问题,出现了一下两个不理解的地方:我是计算机小白,有任何名次运用不当的地方,谢谢指正!
-
首先我在我的主页面,使用这个全局存储的时候,我是首先给了一个默认值是defaultvalue这个值,然后我在运行的时候,无论是普通手机模式,还是折叠屏的折叠模式,他给我的显示都是defaultvalue,并不是我在类中一个函数中,将对应的设备的型号赋值给全局存储的那个值,例如,是手机形式行该显示sm,折叠屏的展开应该实现md,这里他并没有显示sm,而是直接显示的defaultvalue这个值,但是我在折叠屏的折叠状态下把折叠屏展开,他的数值会变成md;但是,让我第一次的运行是在折叠屏的展开状态下时,他就执行的时md,不再是defaultvalue这个值,对于这里不是很理解,一开始以为是:
aboutToAppear
生命周期钩子可能是在页面开始构建之后才执行的,导致AppStorage
的更新发生在build
函数之后,初始值未被覆盖。这个原因,但是直接在折叠屏的展开运行就正常的显示md,这个原因就不成立了。这是一个问题 -
不能检测设备的状态变化,就在我设备从折叠屏的展开状态变为折叠状态后,按理说,他的这个md应该变为sm,但是他没有变化,一直都是md,不知道时什么原因
以上是我的两个疑问,下面是我的主要代码部分:
index.ets部分:
import { BreakPointSystem } from 'common'
// import { MainPage } from 'homelibrary'
import { BasicConstants } from '../Constants/BasicConstants'
import { BreakPointConstants } from 'common'
@Entry
@Component
struct Index {
@State message: string = 'entry index';
//由于我们暴露的是一个类,所以我们必须要new一个实例出来,才能调用里面的方法
private breakpointSystem = new BreakPointSystem();
//private breakpointconstants = new BreakPointConstants();
//为什么这里不用实例化就可以直接访问,在这个类中,我们都是创建的静态对象,但是在BreakPointSystem中,我们创建的都是实例化对象
//解释
//静态成员属于类本身,不需要实例化就可以访问,而实例成员属于类的每个对象,必须通过实例来访问。
// 用户可能没有意识到BreakPointConstants中的CURRENT_BREAKPOINT是静态的,而BreakPointSystem中的方法是非静态的,所以需要实例化才能调用。
//全局存储一下
@StorageProp(BreakPointConstants.CURRENT_BREAKPOINT) currentBreakpoint: string = "sm"
//刚进入界面时
aboutToAppear(): void {
//console.log(add(1,2)+"")
this.breakpointSystem.register() //进入时,我们就注册监听器
}
//组件销毁时
aboutToDisappear(): void {
this.breakpointSystem.unregister() //结束时,我们就要解除绑定,内存有利于回收,不写这个可能会造成内存泄露
}
build() {
Column() {
Text(this.message)
.fontSize(BasicConstants.FONT_SIZE_LARGE)
.fontWeight(FontWeight.Bold)
Text(`当前屏幕的单位是:${this.currentBreakpoint}`)
// //EmptyView()
// MainPage()
Text("纯文本")
}
.height(BasicConstants.FULL_WIDTH)
.width(BasicConstants.FULL_HEIGHT)
}
}
BreakPointSystem.ets部分:
import { BreakPointConstants } from '../constants/BreakPointConstants'
import { mediaquery } from '@kit.ArkUI';
export class BreakPointSystem {
//首先我们要把我们当前屏幕的大小的值保存起来,保存起来以后其他的页面就都可以获取我们当前的屏幕信息了
//媒体查询得到的单位后,我们要及那个sm md保存到全局,这时候我们要将这个currentBreakpoint作为key保存起来
private currentBreakpoint: string = BreakPointConstants.BREAKPOINT_SM //默认的初始值就是手机
//1. 第一步 查看屏幕的大小,并且查询屏幕的大小
private smlistener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_SM); //表示这个是手机范围。返回值是true或false
private mdlistener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_MD); //表示这个是折叠屏范围。返回值是true或false
private lglistener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_LG); //表示这个是平板范围。返回值是true或false
private xllistener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_XL); //表示这个是大屏范围。返回值是true或false
//2. 给监听器绑定一个change事件,
//后面每一个函数内部都要将对应的单位保存起来,我们这里直接抽取出来作为一个公共的函数
//保存当前屏幕的检测见过,sm md lg xl 保存在应用的状态,可以保证所有的页面都可以共享
private updateCurrentBreakpoint(breakpoint: string) {
if (this.currentBreakpoint !== breakpoint) {
this.currentBreakpoint = breakpoint //我的初始单位是手机类型的,如果这时候你传过来的值不是手机类型的我就更新我的数据
//应用存储,存到全局中
AppStorage.setOrCreate<string>(BreakPointConstants.CURRENT_BREAKPOINT, this.currentBreakpoint)
// 手动触发组件的重新渲染
//this.$forceUpdate(); // 或者使用合适的机制触发重新渲染
} else {
AppStorage.setOrCreate<string>(BreakPointConstants.CURRENT_BREAKPOINT, this.currentBreakpoint)
}
}
//手机
private isBreakpointSM = (mediaQueryResult: mediaquery.MediaQueryResult) => {
// 若设备为横屏状态,matches匹配成功,更改相应的页面布局
if (mediaQueryResult.matches) {
//将sm 的单位保存起来
this.updateCurrentBreakpoint(BreakPointConstants.BREAKPOINT_SM)
console.log("这个是一个手机")
}
}
private isBreakpointMD = (mediaQueryResult: mediaquery.MediaQueryResult) => {
// 若设备为横屏状态,matches匹配成功,更改相应的页面布局
if (mediaQueryResult.matches) {
//将MD 的单位保存起来
this.updateCurrentBreakpoint(BreakPointConstants.BREAKPOINT_MD)
console.log("这个是一个折叠屏")
}
}
private isBreakpointLG = (mediaQueryResult: mediaquery.MediaQueryResult) => {
// 若设备为横屏状态,matches匹配成功,更改相应的页面布局
if (mediaQueryResult.matches) {
//将LG 的单位保存起来
this.updateCurrentBreakpoint(BreakPointConstants.BREAKPOINT_LG)
console.log("这个是一个平板")
}
}
private isBreakpointXL = (mediaQueryResult: mediaquery.MediaQueryResult) => {
// 若设备为横屏状态,matches匹配成功,更改相应的页面布局
if (mediaQueryResult.matches) {
//将XL 的单位保存起来
this.updateCurrentBreakpoint(BreakPointConstants.BREAKPOINT_XL)
console.log("这个是一个大屏")
}
}
//3. 这个函数我们外面要调用,绑定监听器
public register() {
//重新初始化一下
this.smlistener = mediaquery.matchMediaSync(BreakPointConstants.BREAKPOINT_SM)
//绑定change事件
this.smlistener.on('change', this.isBreakpointSM)
this.mdlistener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_MD); //表示这个是折叠屏范围。返回值是true或false
this.mdlistener.on('change', this.isBreakpointMD)
this.lglistener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_LG); //表示这个是平板范围。返回值是true或false
this.lglistener.on('change', this.isBreakpointLG)
this.xllistener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_XL); //表示这个是大屏范围。返回值是true或false
this.xllistener.on('change', this.isBreakpointXL)
}
//解绑设备
public unregister() {
this.smlistener.off('change',this.isBreakpointSM)
this.mdlistener.off('change',this.isBreakpointMD)
this.lglistener.off('change',this.isBreakpointLG)
this.xllistener.off('change',this.isBreakpointXL)
}
}
BreakPointConstants.ets部分:
//媒体查询的断点常量
export class BreakPointConstants {
/** * Constants for breakpoint. */
/** * 这个单位页面上表示手机 xs就没有加入 */
static readonly BREAKPOINT_SM: string = 'sm';
/** * 折叠屏可以用md来表示 */
static readonly BREAKPOINT_MD: string = 'md';
/** * 一般pad端可以用lg的来表示 */
static readonly BREAKPOINT_LG: string = 'lg';
static readonly BREAKPOINT_XL: string = 'xl';
/** * The break point value. */
static readonly BREAKPOINT_VALUE: Array<string> = ['320vp', '600vp', '840vp', "1200vp"];
/** * The number of columns for SM device. */
//列数
static readonly COLUMN_SM: number = 4;
/** * The number of columns for MD device. */
static readonly COLUMN_MD: number = 8;
/** * The number of columns for LG device. */
static readonly COLUMN_LG: number = 12;
/** * The number of gutter X for device. */
static readonly GUTTER_X: number = 12;
/** * The number of span for SM device. */
static readonly SPAN_SM: number = 4;
/** * The number of span for MD device. */
static readonly SPAN_MD: number = 6;
/** * The number of span for LG device. */
static readonly SPAN_LG: number = 8;
/** * The number of offset for MD device. */
static readonly OFFSET_MD: number = 1;
/** * The number of offset for LG device. */
static readonly OFFSET_LG: number = 2;
/** * Current breakpoints that to query the device types. */
//当前的单位
static readonly CURRENT_BREAKPOINT: string = 'currentBreakpoint';
/** * Font size of the small device type. */
static readonly FONT_SIZE_SM: number = 14;
/** * Font size of the middle device type. */
static readonly FONT_SIZE_MD: number = 16;
/** * Font size of the large device type. */
static readonly FONT_SIZE_LG: number = 18;
/** * Cover margin of the small device type. */
static readonly COVER_MARGIN_SM: number = 10;
/** * Cover margin of the middle device type. */
static readonly COVER_MARGIN_MD: number = 30;
/** * Cover margin of the large device type. */
static readonly COVER_MARGIN_LG: number = 40;
/** * Range of the small device width. */
static readonly RANGE_SM: string = '(320vp<=width<600vp)';
/** * Range of the middle device width. */
static readonly RANGE_MD: string = '(600vp<=width<840vp)';
/** * Range of the large device width. */
static readonly RANGE_LG: string = '(840vp<=width<1200vp)';
static readonly RANGE_XL: string = '(1200vp<=width)';
}
效果展示不能上传视频,抱歉啦!
更多关于HarmonyOS 鸿蒙Next 媒体查询中,折叠屏手机折叠起来,监听器监听不到的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
register函数更新一下:
public register() {
//重新初始化一下
this.smlistener = mediaquery.matchMediaSync(BreakPointConstants.BREAKPOINT_SM)
this.updateCurrentBreakpoint(BreakPointConstants.BREAKPOINT_SM)
//绑定change事件
this.smlistener.on('change', this.isBreakpointSM)
this.mdlistener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_MD); //表示这个是折叠屏范围。返回值是true或false
this.updateCurrentBreakpoint(BreakPointConstants.BREAKPOINT_MD)
this.mdlistener.on('change', this.isBreakpointMD)
this.lglistener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_LG); //表示这个是平板范围。返回值是true或false
this.updateCurrentBreakpoint(BreakPointConstants.BREAKPOINT_LG)
this.lglistener.on('change', this.isBreakpointLG)
this.xllistener = mediaquery.matchMediaSync(BreakPointConstants.RANGE_XL); //表示这个是大屏范围。返回值是true或false
this.updateCurrentBreakpoint(BreakPointConstants.BREAKPOINT_XL)
this.xllistener.on('change', this.isBreakpointXL)
}
更多关于HarmonyOS 鸿蒙Next 媒体查询中,折叠屏手机折叠起来,监听器监听不到的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
谢谢你呀,刚才试了一下,这样是不可以的,后面每一次都调用一次updateCurrentBreakpoint
这个函数,后面的会把前面的值覆盖掉,这个函数不能单独拿出来调用。
-
可以先判断是什么设备,在aboutToAppear的时候就使用deviceInfo.deviceType来获取出是平板还是手机什么的设备。
-
如果是折叠屏可以试下使用getFoldStatus来判断折叠屏的状态呢,比如:
import { display } from '@kit.ArkUI';
let data: display.FoldStatus = display.getFoldStatus();
console.info('Succeeded in obtaining fold status. Data: ' + JSON.stringify(data));
然后根据FoldStatus来判断目前的屏幕展开状态。
你是目前折叠手机的适配员吗?
不是不是,我就是一个大四的学生哈哈哈,
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html
调用的时候,函数体里面的所有内容都会执行,这个updateCurrentBreakpoint函数就是一个赋值函数,他不存在判断,肯定就是调用一次复制一次,最后的结果就是最后调用的结果呀,我试了你上面给我说的都添加一下updateCurrentBreakpoint这个的方法,测试的是不可以的。
针对HarmonyOS鸿蒙Next系统中,折叠屏手机在折叠状态下媒体查询的监听器无法正常工作的问题,可能的原因及解决方案如下:
-
系统权限与配置:
- 确保应用已获得必要的系统权限,特别是与屏幕状态变化相关的权限。
- 检查应用是否在系统设置中启用了对折叠屏状态变化的监听功能。
-
监听器实现:
- 验证监听器的实现是否正确,包括注册与注销逻辑是否完善。
- 确认监听器是否针对正确的屏幕状态变化事件进行了注册。
-
系统兼容性:
- 检查当前使用的鸿蒙系统版本是否支持折叠屏状态的监听。
- 尝试在不同型号的折叠屏手机上复现问题,以排除特定硬件或软件版本的问题。
-
代码与逻辑检查:
- 仔细检查与监听器相关的代码逻辑,确保没有遗漏或错误。
- 使用日志输出等方式,验证监听器是否被正确触发和执行。
如果上述方法均未能解决问题,可能是由于系统或硬件层面的特定问题导致。此时,建议联系鸿蒙系统的官方技术支持团队进行进一步的排查和解决。如果问题依旧没法解决请联系官网客服,官网地址是 https://www.itying.com/category-93-b0.html,