Flutter Widgets 之 MediaQuery控件获取屏幕信息

MediaQuery


通常情况下,不会直接将MediaQuery当作一个控件,而是使用MediaQuery.of获取当前设备的信息,用法如下:

var data = MediaQuery.of(context);

此方式必须放在MediaQuery作用域内,否则会抛出异常,MaterialApp和WidgetsApp都引入了MediaQuery,并且随着屏幕的变化而导致重建,比如旋转屏幕、弹出输入框等。

MediaQueryData

MediaQueryData是MediaQuery.of获取数据的类型。说明如下:

属性说明
size逻辑像素,并不是物理像素,类似于Android中的dp,逻辑像素会在不同大小的手机上显示的大小基本一样,物理像素 = size*devicePixelRatio。
devicePixelRatio单位逻辑像素的物理像素数量,即设备像素比。
textScaleFactor单位逻辑像素字体像素数,如果设置为1.5则比指定的字体大50%。
platformBrightness当前设备的亮度模式,比如在Android Pie手机上进入省电模式,所有的App将会使用深色(dark)模式绘制。
viewInsets被系统遮挡的部分,通常指键盘,弹出键盘,viewInsets.bottom表示键盘的高度。
padding被系统遮挡的部分,通常指“刘海屏”或者系统状态栏。
viewPadding被系统遮挡的部分,通常指“刘海屏”或者系统状态栏,此值独立于paddingviewInsets,它们的值从MediaQuery控件边界的边缘开始测量。在移动设备上,通常是全屏。
systemGestureInsets显示屏边缘上系统“消耗”的区域输入事件,并阻止将这些事件传递给应用。比如在Android Q手势滑动用于页面导航(ios也一样),比如左滑退出当前页面。
physicalDepth设备的最大深度,类似于三维空间的Z轴。
alwaysUse24HourFormat是否是24小时制。
accessibleNavigation用户是否使用诸如TalkBack或VoiceOver之类的辅助功能与应用程序进行交互,用于帮助视力有障碍的人进行使用。
invertColors是否支持颜色反转。
highContrast用户是否要求前景与背景之间的对比度高, iOS上,方法是通过“设置”->“辅助功能”->“增加对比度”。此标志仅在运行iOS 13的iOS设备上更新或以上。
disableAnimations平台是否要求尽可能禁用或减少动画。
boldText平台是否要求使用粗体。
orientation是横屏还是竖屏。

获取设备相关信息:

 
import 'package:demo202112/utils/common_appbar.dart';
import 'package:flutter/cupertino.dart';
import "package:flutter/material.dart";
 
class WyMediaQuery extends StatefulWidget {
  const WyMediaQuery({Key? key}) : super(key: key);
 
  @override
  _WyMediaQueryState createState() => _WyMediaQueryState();
}
 
class _WyMediaQueryState extends State<WyMediaQuery> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: getAppBar('MediaQuery'),
      body: MediaQuery(data: const MediaQueryData(),
      child: _getDeviceMediaInfo(),),
    );
  }
  _getDeviceMediaInfo(){
    //屏幕大小
    Size mSize = MediaQuery.of(context).size;
    //密度
    double mRatio = MediaQuery.of(context).devicePixelRatio;
    //设备像素
    double width = mSize.width * mRatio;
    double height = mSize.height * mRatio;
    // 上下边距 (主要用于 刘海  和  内置导航键)
    double topPadding = MediaQuery.of(context).padding.top;
    double bottomPadding = MediaQuery.of(context).padding.bottom;
    double textScaleFactor = MediaQuery.of(context).textScaleFactor;
 
    Brightness platformBrightness = MediaQuery.of(context).platformBrightness;
    EdgeInsets viewInsets = MediaQuery.of(context).viewInsets;
    EdgeInsets padding = MediaQuery.of(context).padding;
    bool alwaysUse24HourFormat = MediaQuery.of(context).alwaysUse24HourFormat;
    bool accessibleNavigation = MediaQuery.of(context).accessibleNavigation;
    bool invertColors = MediaQuery.of(context).invertColors;
    bool disableAnimations = MediaQuery.of(context).disableAnimations;
    bool boldText = MediaQuery.of(context).boldText;
    Orientation orientation= MediaQuery.of(context).orientation;
    // bool alwaysUse24HourFormat = MediaQuery.of(context).alwaysUse24HourFormat;
    return Container(
      padding: EdgeInsets.all(30),
      child: Column(
      children: [
        Text('屏幕大小:${mSize.width} x ${mSize.height}'),
        Text('密度:${mRatio}'),
        Text('设备像素大小:${width} x ${height}'),
        Text('上边刘海:${topPadding}'),
        Text('下边导航:${bottomPadding}'),
 
        Text('textScaleFactor: ${textScaleFactor}'),
        Text('platformBrightness: ${platformBrightness}'),
        Text('viewInsets: ${viewInsets}'),
        Text('padding: ${padding}'),
        Text('alwaysUse24HourFormat: ${alwaysUse24HourFormat}'),
        Text('accessibleNavigation: ${accessibleNavigation}'),
        Text('invertColors: ${invertColors}'),
        Text('disableAnimations: ${disableAnimations}'),
        Text('boldText: ${boldText}'),
        Text('orientation: ${orientation}'),
        Text('orientation: ${orientation}'),
 
 
      ],
    ),);
 
 
 
  }
}
 
 

效果:

 

随着屏幕旋转,设备信息跟着屏幕方向在变动。

使用场景


根据尺寸构建不同的布局

SafeArea控件就是通过MediaQuery.of来实现的,平板和手机的(或者横屏和竖屏)布局可能是不一样的,布局判断:

var screenSize = MediaQuery.of(context).size;
if(screenSize.width>oneColumnLayout){
  //平板布局
}else{
  //手机布局
}

 

oneColumnLayout表示一列布局的宽度。

系统字体变化


很多App都有一个功能就是调节字体大小,通过MediaQuery来实现,实现如下:

  //textScaleFactor 从1变到1.5,字体会全部增大
    var _data = MediaQuery.of(context).copyWith(textScaleFactor: 1.0);
    return Scaffold(
      appBar: getAppBar('MediaQuery'),
      body: MediaQuery(data: _data,
      child: _getDeviceMediaInfo(),),
    );

 

源码地址:

dy flutter_demo: flutter组件测试学习demo正在上传…重新上传取消https://gitee.com/wywinstonwy/flutter_demo

 

Flutter MediaQuery获取屏幕信息以及屏幕适配

使用MediaQuery获取屏幕高宽等信息

  • MediaQuery.devicePixelRatio 每一个逻辑像素点对应的物理像素点个数
  • MediaQuery.size.width 用逻辑像素表示的屏幕宽度
  • MediaQuery.size.height 用逻辑像素表示的屏幕高度
  • MediaQuery.padding.top 屏幕上部被系统UI遮挡的部分的逻辑高度(即:状态栏高度)
  • MediaQuery.textScaleFactor 显示文字时,每一个逻辑像素对应的字体像素

讲解

Flutter中控件的高宽和字体大小时,使用的是逻辑像素,并非是实际的物理像素。

实际像素=逻辑像素*MediaQuery.devicePixelRatio

flutter中的屏幕适配

image.png

假设设计图的大小为1080 X 1920,上面一个图片的高度为 80 X 90,则它在设备上的高宽为

 MediaQueryData mediaQuery = MediaQuery.of(context);
 width=80*(mediaQuery.size.width)/(1080)
 height=90*(mediaQuery.size.width)/(1080)

对于android手机,一般以宽度为基准计算UI的高宽,因为android手机的宽度一般就是750,1080等几个尺寸,但是高的尺寸就有很多。

推荐一个别人封装好的一个用于屏幕适配的库
Flutter屏幕适配方案插件-完美解决屏幕适配

0人点赞


链接:https://www.jianshu.com/p/4ef258d0f5e5
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

参考:

20、 Flutter Widgets 之 MediaQuery控件获取屏幕信息_风雨「83」的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值