flutter实战-MediaQuery
![](https://img.haomeiwen.com/i28281950/a331bd01662d9f5f.jpeg)
用了两年的flutter,有了一些心得,从今天开始陆续更新一些案例,不虚头巴脑,只求实战有用,以供学习或使用flutter的小伙伴参考,学习尚浅,如有不正确的地方还望各路大神指正,以免误人子弟,在此拜谢~(原创不易,转发请标注来源和作者)
注意:无特殊说明,flutter版本为3.0+
今天重点解析一下MediaQuery,为什么会讲这个,作为一个使用者,在使用的前一年中,基本上没有用到这个东西(可能做的需求不够复杂),但是在各大插件中大量使用,希望初学者可以重视~
一。 MediaQuery
MediaQuery字面意思就是媒体查询, 废话不多说,先看官方概念:
/// Establishes a subtree in which media queries resolve to the given data.
///
/// For example, to learn the size of the current media (e.g., the window
/// containing your app), you can read the [MediaQueryData.size] property from
/// the [MediaQueryData] returned by [MediaQuery.of]:
/// `MediaQuery.of(context).size`.
///
/// Querying the current media using [MediaQuery.of] will cause your widget to
/// rebuild automatically whenever the [MediaQueryData] changes (e.g., if the
/// user rotates their device).
///
/// If no [MediaQuery] is in scope then the [MediaQuery.of] method will throw an
/// exception. Alternatively, [MediaQuery.maybeOf] may be used, which returns
/// null instead of throwing if no [MediaQuery] is in scope.
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=A3WrA4zAaPw}
///
/// See also:
///
/// * [WidgetsApp] and [MaterialApp], which introduce a [MediaQuery] and keep
/// it up to date with the current screen metrics as they change.
/// * [MediaQueryData], the data structure that represents the metrics.
class MediaQuery extends InheritedWidget {
总结如下:
1.通过MediaQuery.of(context)获取当前组件上下文的媒体数据,当然可能不存在,建议使用MediaQuery.maybeOf(context)。
2.可在横竖屏切换的时候进行查询当前窗口情况。
既然是查询,自然有返回结果,下面引出我们第二个重点概念
二。MediaQueryData
MediaQueryData,我们先看概念重点部分:
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,
this.gestureSettings = const DeviceGestureSettings(touchSlop: kTouchSlop),
this.displayFeatures = const <ui.DisplayFeature>[],
})
1.size:逻辑像素,非物理像素,跟他可以获得屏幕尺寸
2.重点padding,viewInsets,viewPadding
padding:被系统UI遮挡的部分,比如刘海屏或者状态栏
viewInsets:被系统UI遮挡的部分,通常指键盘
viewPadding:被系统UI遮挡的部分,值从MediaQuery控件边界的边缘开始测量,独立于padding和viewInsets
![](https://img.haomeiwen.com/i28281950/6c867f0cc4120564.jpeg)
其中padding的值是由viewPadding和viewInsets计算而来,公式如下
padding = max(0.0, viewPadding - viewInsets)
看一个官方例子:
![](https://img.haomeiwen.com/i28281950/a5a233a0cc5924df.jpeg)
![](https://img.haomeiwen.com/i28281950/807d223bba79cb9d.jpeg)
当键盘弹出,viewInsets高度320,padding由公式计算(viewPadding - viewInsets)为负值,所以计为0
理解了概念,就不难理解对应的三个方法,就是移除padding
1.removePadding
使用场景举例:去除ListView.builder的默认padding
当在滑动视图中使用ListView(继承于SliverList),会默认添加一个SilverPadding,官方解释如下
/// * [SliverPadding], which is a sliver that adds blank space around another
/// sliver.
使用:
...
SingleChildScrollView(child:
MediaQuery.removePadding(
context: context,
removeTop: true,
removeBottom: true,
child:ListView.builder(...
2.removeViewPadding
暂时还没使用过
3.removeViewInsets
在Scaffold源码和Dialog中均有使用
三。实践
//屏幕大小
Size mSize = MediaQuery.of(context).size;
//密度
double mRatio = MediaQuery.of(context).devicePixelRatio;
//设备像素
double width = mSize.width * mRatio;
double height = mSize.height * mRatio;
结语:概念讲一下,具体实践还要看使用场景,为什么会讲这个,后面会更新一些自定义键盘的实践代码会用到相关概念,感谢关注~