# 2.8:媒体查询

媒体查询(Media Query)在移动设备上应用十分广泛,开发者经常需要根据设备的大致类型或者特定的特征和设备参数(例如屏幕分辨率)来修改应用的样式。ArkUI开发框架在 @kit.ArkUI 模块里提供了 API 实现对设备特性变更的监听,本节笔者介绍一下媒体查询的简单使用。

# 2.8.1:媒体查询功能介绍

媒体查询在 @kit.ArkUI 模块里提供的主要功能如下所示:

  • 针对设备和应用的属性信息,可以设计出相匹配的布局样式。
  • 当屏幕发生动态改变时(比如分屏、横竖屏切换),应用页面布局同步更新。

# 2.8.2:媒体查询定义介绍

declare namespace mediaquery {

  // 获取MediaQueryListener监听器
  function matchMediaSync(condition: string): MediaQueryListener;
  
  interface MediaQueryResult {
    readonly matches: boolean;
    readonly media: string;
  }

  interface MediaQueryListener extends MediaQueryResult {
    // 监听变化
    on(type: 'change', callback: Callback<MediaQueryResult>): void;
    // 取消监听
    off(type: 'change', callback?: Callback<MediaQueryResult>): void;
  }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

监听设备特征发生变化,先通过 mediaquery 提供的 matchMediaSync() 方法获取一个 MediaQueryListener 类型的监听器,然后调用该监听器的 on()off() 方法开启和关闭监听。

# 2.8.3:媒体查询语法介绍

通过调用媒体查询接口 matchMediaSync(),设置媒体查询条件和查询结果的回调函数,在对应的条件的回调函数里更改页面布局或者实现业务逻辑。matchMediaSync() 方法的 condition 参数要求语法格式如下:

[media-type] [and|not|only] [(media-feature)]
1
  • media-type: 媒体类型,参数支持 screen 等,表示查询条件按屏幕相关参数进行媒体查询。

  • and | not | only | or: 媒体逻辑操作符,用于构成复杂媒体查询,也可以通过comma(,)将其组合起来,详细解释说明如下表。

    类型 说明
    and 将多个媒体特征(Media Feature)以 的方式连接成一个媒体查询,只有当所有媒体特征都为 true ,查询条件成立。另外,它还可以将媒体类型和媒体功能结合起来。例如:
    screen and (device-type: wearable) and (max-height: 600): 表示当设备类型是智能穿戴同时应用的最大高度小于等于 600 个像素单位时成立。
    not 取反媒体查询结果,媒体查询结果不成立时返回 true ,否则返回 false 。在媒体查询列表中应用 not ,则 not 仅取反应用它的媒体查询。 例如:
    not screen and (min-height: 50) and (max-height: 600): 表示当应用高度小于 50 个像素单位或者大于 600 个像素单位时成立。
    📢:使用 not 运算符时必须指定媒体类型。
    only 当整个表达式都匹配时,才会应用选择的样式,可以应用在防止某些较早的版本的浏览器上产生歧义的场景。一些较早版本的浏览器对于同时包含了媒体类型和媒体特征的语句会产生歧义,例如:
    screen and (min-height: 50): 老版本浏览器会将这句话理解成 screen,从而导致仅仅匹配到媒体类型(screen),就应用了指定样式,使用only可以很好地规避这种情况。
    📢:使用 only 时必须指定媒体类型。
    , (comma) 将多个媒体特征以 的方式连接成一个媒体查询,如果存在结果为 true 的媒体特征,则查询条件成立。其效果等同于 or 运算符。 例如:
    screen and (min-height: 1000), (round-screen:true): 表示当应用高度大于等于 1000 个像素单位或者设备屏幕是圆形时,条件成立。
    or 将多个媒体特征以 的方式连接成一个媒体查询,如果存在结果为 true 的媒体特征,则查询条件成立。 例如:
    screen and (max-height: 1000) or (round-screen:true): 表示当应用高度小于等于 1000 个像素单位或者设备屏幕是圆形时,条件成立。

    媒体逻辑范围操作符说明如下:

    类型 说明
    <= 小于等于,例如:screen and (50 <= height)。
    >= 大于等于,例如:screen and (600 >= height)。
    < 小于,例如:screen and (50 < height)。
    > 大于,例如:screen and (600 > height)。
  • media-feature:媒体特征,具体说明如下表格所示:

    类型 说明
    height 应用页面显示区域的高度。
    min-height 应用页面显示区域的最小高度。
    max-height 应用页面显示区域的最大高度。
    width 应用页面显示区域的宽度。
    min-width 应用页面显示区域的最小宽度。
    max-width 应用页面显示区域的最大宽度。
    resolution 设备的分辨率,支持dpi,dppx和dpcm单位。其中:
    1、dpi表示每英寸中物理像素个数,1dpi≈0.39dpcm;
    2、dpcm表示每厘米上的物理像素个数,1dpcm ≈ 2.54dpi;
    3、dppx表示每个px中的物理像素数,1dppx = 96dpi。
    min-resolution 设备的最小分辨率。
    max-resolution 设备的最大分辨率。
    orientation 屏幕的方向。 可选值:
    orientation: portrait(设备竖屏)
    orientation: landscape(设备横屏)
    device-height 设备的高度。
    min-device-height 设备的最小高度。
    max-device-height 设备的最大高度。
    device-width 设备的宽度。
    min-device-width 设备的最小宽度。
    max-device-width 设备的最大宽度。
    round-screen 屏幕类型,圆形屏幕为 true , 非圆形屏幕为 false
    dark-mode 系统为深色模式时为 true ,否则为 false

# 2.8.4:媒体查询使用介绍

通过调用媒体查询接口 matchMediaSync(),设置媒体查询条件和查询结果的回调函数,在对应的条件的回调函数里更改页面布局或者实现业务逻辑。用法如下所示:

  • 导入媒体查询模块

    import { mediaquery } from '@kit.ArkUI';
    
    1
  • 调用媒体查询方法

    let mediaListener = mediaquery.matchMediaSync("(orientation: landscape)");
    
    1
  • 监听设备特性变更

    mediaListener.on("change", (result) => {
      if(result) {
        if(result.matches) {
          // 满足条件,实现相应业务逻辑
        } else {
          // 不满足条件,实现相应业务逻辑
        }
      }
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  • 取消监听设备变更

    mediaListener.off("change");
    
    1

# 2.8.5:媒体查询完整样例

通过使用媒体查询实现当屏幕发生横竖屏切换,给页面文本应用不同的内容和样式。

import { mediaquery } from '@kit.ArkUI';

@Entry @Component struct mediaQueryTest {

  private mediaListener?: mediaquery.MediaQueryListener | null = null

  @State color: string = '#DB7093';
  @State text: string = 'Portrait';
  @State fontSize: number = 50;

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Text(this.text)
        .fontSize(this.fontSize)
        .fontColor(this.color)
    }
    .width('100%')
    .height('100%')
  }

  aboutToAppear() {
    // 获取监听器
    this.mediaListener = mediaquery.matchMediaSync("(orientation: landscape)");
    // 开始监听
    this.mediaListener.on("change", (result: mediaquery.MediaQueryResult) => {
      if(result) {
        if(result.matches) {
          // 满足条件,实现相应业务逻辑
          this.color = '#FFD700'
          this.text = 'Landscape'
        } else {
          // 不满足条件,实现相应业务逻辑
          this.color = '#DB7093'
          this.text = 'Portrait'
        }
      }

    });
  }

  aboutToDisappear() {
    // 取消监听
    this.mediaListener?.off("change");
  }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

竖屏下文本内容为 Portrait ,颜色为 #DB7093 ,效果如下图所示:

2_8_5_1

横屏下文本内容为 Landscape ,颜色为 #FFD700 ,效果如下图所示:

2_8_5_2
(adsbygoogle = window.adsbygoogle || []).push({});
请作者喝杯咖啡

津公网安备 12011402001367号

津ICP备2020008934号-2

中央网信办互联网违法和不良信息举报中心

天津市互联网违法和不良信息举报中心