Code前端首页关于Code前端联系我们

MediaQuery——flutter移动开发中查询设备信息的利器

terry 2年前 (2023-09-22) 阅读数 82 #移动小程序

在移动开发中,不同设备的规格可能是大家最大的问题。现在设备这么多,我们如何在众多设备中找到合适的widget位置呢?画画呢?

别担心,Flutter为我们提供了一个利器,叫MediaQuery,我们来看看吧。

MediaQuery详解

MediaQuery 从名字上看,就是媒体询问的意思。它可以查询很多东西,它可以查询你的应用程序当前窗口的信息,它可以查询你指定的一个小部件的信息等等。它非常强大。

首先我们来看看MediaQuery是什么。具体来说,MediaQuery继承了InheritedWidget:

class MediaQuery extends InheritedWidget 

那么InheritedWidget是什么?为什么MediaQuery需要InheritedWidget的继任者?

很多时候我们需要从widget的子widget中获取父widget对象。 InheritedWidget是一个可以提供简单获取方法的对象。

在InheritedWidget中可以实现of方法,通过调用BuildContext.dependOnInheritedWidgetOfExactType可以从上下文中获取最近的InheritedWidget对象。

这里,由于MediaQuery是一个媒体查询工具,我们可能需要在任何时间、很多地方获取对象,所以这里最好使用InheritedWidget。

MediaQuery 属性

MediaQuery 只有两个属性,分别是 MediaQuery 数据类型的数据和 Widget 类型的后代。

MediaQuery数据是一种类似类的结构,用于存储有关各种媒体状态的信息。

首先,让我们看一下MediaQuery数据构造器:

const MediaQueryData({
    this.size = Size.zero,
    this.devicePixelRatio = 1.0,
    this.textScaleFactor = 1.0,
    this.platformBrightness = Brightness.light,
    this.padding = EdgeInsets.zero,
    this.viewInsets = EdgeInsets.zero,
    this.systemGestureInsets = EdgeInsets.zero,
    this.viewPadding = EdgeInsets.zero,
    this.alwaysUse24HourFormat = false,
    this.accessibleNavigation = false,
    this.invertColors = false,
    this.highContrast = false,
    this.disableAnimations = false,
    this.boldText = false,
    this.navigationMode = NavigationMode.traditional,
  })

正如你所看到的,MediaQuery数据包含许多有用的属性。下面我们来详细了解一下具体内容。

第一个是尺寸,表示媒体逻辑像素的尺寸。大家要注意,这里的尺寸代表的是逻辑像素尺寸。

有逻辑像素和物理像素。前者表示在任何设备上都相同的逻辑大小,而后者表示实际物理设备支持的像素大小。两者可以不同。一个物理像素可以代表多个逻辑像素,这种匹配由 devicePixelRatio 属性确定。

devicePixelRatio 表示有多少个逻辑像素代表一个物理像素。 devicePixelRatio 不需要是整数。例如,在 Nexus 6 设备上,此 devicePixelRatio=3.5。

接下来是textScaleFactor,它表示一个逻辑像素可以表示多少个字体像素。或者您可以将其视为字体大小。

例如textScaleFactor=1.5,那么就表示渲染的字体比给定的字体大50%。

然后是平台亮度,代表设备亮度。最常见的是明亮模式或黑暗模式。

viewInsets 表示被系统用户界面完全覆盖的部分。例如,当我们进行键盘输入时,就会弹出键盘界面。

填充表示被系统用户界面部分覆盖且不完全可见的部分。通常是系统状态栏,就像iPhone上的伤口一样。

viewPadding 表示被系统用户界面部分覆盖、无法完全看到的部分。通常是系统状态栏,就像iPhone上的伤口一样。

哇,看起来padding和viewPadding是一样的,但这是真的吗?

两者通常是相同的,只有在出现键盘输入界面时才会有所不同。

简单来说,viewPadding 是固定的,其大小不随键盘视图的变化而改变。衬垫是可更换的。当键盘展开且系统状态栏隐藏时,其底部值为0。

systemGestureInsets 是一个特殊的手势区域。该区域只能识别部分手势指令,而不是所有手势指令,所以需要这样的属性。

alwaysUse24HourFormat表示是否使用24小时时间格式。

accessibleNavigation 指示用户是否使用任何辅助服务与应用程序交互。

还有其他可以使用的基本功能,例如高对比度、禁用动画、粗体文本、导航模式和方向。

MediaQuery的另一个属性是孩子。

MediaQuery构造函数

除了最常见的构造函数之外,MediaQuery还有三个构造函数,分别是Future.removePadding、Future.removeViewInsets、Future.removeViewPadding。

这三个构造函数都是通过传入指定的 context 和 child 来构造 MediaQuery 的,但是它们都相应地删除了一些属性。从名字就可以看出,这三个缩进分别是padding、viewInsets和viewPadding。

我们以removePadding为例来看一下具体的实现过程:

  factory MediaQuery.removePadding({
    Key? key,
    required BuildContext context,
    bool removeLeft = false,
    bool removeTop = false,
    bool removeRight = false,
    bool removeBottom = false,
    required Widget child,
  }) {
    return MediaQuery(
      key: key,
      data: MediaQuery.of(context).removePadding(
        removeLeft: removeLeft,
        removeTop: removeTop,
        removeRight: removeRight,
        removeBottom: removeBottom,
      ),
      child: child,
    );
  }

removePadding方法必须额外传递四个参数,表示是否去除左、上、右、下的padding。 。

我们看到返回了一个新的MediaQuery,其中data部分使用MediaQuery.of(context)获取上下文中最接近的MediaQuery,然后调用其removePadding方法去除对应的padding属性。

使用MediaQuery

说完了MediaQuery的构造函数,我们再来看看使用MediaQuery的常用场景。

其实,使用MediaQuery最常见的方式就是判断设备尺寸,这样就可以根据不同设备的尺寸来调整页面。

比如下面的getSize方法:

enum ScreenSize { Small, Normal, Large, ExtraLarge }

ScreenSize getSize(BuildContext context) {
  double deviceWidth = MediaQuery.of(context).size.shortestSide;
  if (deviceWidth > 900) return ScreenSize.ExtraLarge;
  if (deviceWidth > 600) return ScreenSize.Large;
  if (deviceWidth > 300) return ScreenSize.Normal;
  return ScreenSize.Small;
}

我们通过MediaQuery.of(context)获取到了MediaQuery,然后我们利用size的shortestSide属性得到了设备的宽度,然后我们具体宽度根据设备的宽度进行比较,确定设备的屏幕尺寸。

MediaQuery当然也可以用在其他需要确定媒体属性的地方。大家可以仔细体验一下。

总结

MediaQuery是flutter中一个非常方便的工具,用于检测媒体属性。按照MediaQuery的说法,我们可以创建一个更具互动性的APP。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门