欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > > 内容正文

FlutterWidgetsMediaQuery控件屏幕信息适配,

来源: 开发者 投稿于  被查看 35140 次 评论:67

FlutterWidgetsMediaQuery控件屏幕信息适配,


目录
  • MediaQuery
  • MediaQueryData
  • 使用场景
    • 根据尺寸构建不同的布局
  • 系统字体变化
    • 第三方屏幕的适配框架:
      • 设置字体不随系统字体大小进行改变 APP全局
    • 总结:

      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被系统遮挡的部分,通常指“刘海屏”或者系统状态栏,此值独立于padding和viewInsets,它们的值从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(),),
          );
      

      运行效果:

      第三方屏幕的适配框架:

      flutter_screenutil:用于调整屏幕和字体大小的颤振插件。让你的UI在不同的屏幕尺寸上显示合理的布局!

      api适配:

          ScreenUtil().setWidth(540)  (dart sdk>=2.6 : 540.w)   //根据屏幕宽度适配尺寸
          ScreenUtil().setHeight(200) (dart sdk>=2.6 : 200.h)   //根据屏幕高度适配尺寸(一般根据宽度适配即可)
          ScreenUtil().radius(200)    (dart sdk>=2.6 : 200.r)   //根据宽度或高度中的较小者进行调整
          ScreenUtil().setSp(24)      (dart sdk>=2.6 : 24.sp)   //适配字体
          12.sm   // 取12和12.sp中的最小值
          ScreenUtil.pixelRatio       //设备的像素密度
          ScreenUtil.screenWidth   (dart sdk>=2.6 : 1.sw)   //设备宽度
          ScreenUtil.screenHeight  (dart sdk>=2.6 : 1.sh)   //设备高度
          ScreenUtil.bottomBarHeight  //底部安全区距离,适用于全面屏下面有按键的
          ScreenUtil.statusBarHeight  //状态栏高度 刘海屏会更高
          ScreenUtil.textScaleFactor //系统字体缩放比例
          ScreenUtil().scaleWidth  // 实际宽度设计稿宽度的比例
          ScreenUtil().scaleHeight // 实际高度与设计稿高度度的比例
          ScreenUtil().orientation  //屏幕方向
          0.2.sw  //屏幕宽度的0.2倍
          0.5.sh  //屏幕高度的50%
          20.setVerticalSpacing  // SizedBox(height: 20 * scaleHeight)
          20.horizontalSpace  // SizedBox(height: 20 * scaleWidth)
          const RPadding.all(8)   // Padding.all(8.r) - 获取到const的优点
          REdgeInsts.all(8)       // EdgeInsets.all(8.r)
          EdgeInsets.only(left:8,right:8).r // EdgeInsets.only(left:8.r,right:8.r).
      

      适配字体

      //输入字体大小(单位与初始化时的单位相同)
      ScreenUtil().setSp(28) 
      28.sp
      //例子:
      Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Text(
            '16sp, 因为设置了`textScaleFactor`,不会随系统变化.',
            style: TextStyle(
              color: Colors.black,
              fontSize: 16.sp,
            ),
            textScaleFactor: 1.0,
          ),
          Text(
            '16sp,如果未设置,我的字体大小将随系统而变化.',
            style: TextStyle(
              color: Colors.black,
              fontSize: 16.sp,
            ),
          ),
        ],
      )
      

      设置字体不随系统字体大小进行改变 APP全局

             MaterialApp(
              debugShowCheckedModeBanner: false,
              title: 'Flutter_ScreenUtil',
              theme: ThemeData(
                primarySwatch: Colors.blue,
              ),
              builder: (context, widget) {
                return MediaQuery(
                  ///设置文字大小不随系统设置改变
                  data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
                  child: widget,
                );
              },
              home: HomePage(title: 'FlutterScreenUtil Demo'),
            ),
      

      单独的Text:

      Text("text", textScaleFactor: 1.0)
      

      指定的小部件:

      MediaQuery(
        // 如果这里context不可用,你可以新建一个 [Builder] 将 [MediaQuery] 放入其中
        data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
        child: AnyWidget(),
      )
      

      总结:

      本篇主要介绍了系统组价MediaQuery的基本参数和基本使用情况,以及扩展第三方屏幕适配组件flutter_screenutil.

      以上就是Flutter Widgets MediaQuery控件屏幕信息适配的详细内容,更多关于Flutter Widgets MediaQuery的资料请关注3672js教程其它相关文章!

      您可能感兴趣的文章:
      • Android开发Flutter 桌面应用窗口化实战示例
      • Canonical通过Flutter启用Linux桌面应用程序(推荐)
      • Flutter应用框架搭建实现屏幕适配方案详解
      • Flutter应用框架搭建之屏幕适配详解
      • 详解Flutter桌面应用如何进行多分辨率适配

      用户评论