Flutter Widgets MediaQuery控件屏幕信息适配

目录
  • 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的资料请关注我们其它相关文章!

(0)

相关推荐

  • Flutter Widget 之package mason实现详解

    目录 正文 使用Mason砖块 运行mason make 正文 Flutter有个悠久的传统,便是运行flutter create并删除所有内容,然后在所有标准样板文件(boilerplate)当中尽力复制和粘贴,这很费时又容易出错,而且比报税更无趣,但是是否别无他法? 进入Mason,这是用于欧快速组装新项目或功能的软件包,可以从成为“砖块”的自定义模版中生成代码,而这些模版根据你的项目的特定值呈现 使用Mason砖块 例如想象一下,你正为Flutter新项目使用Mason砖块的pubspec

  • flutter InheritedWidget使用方法总结

    目录 引言 didChangeDependencies 如何使用? 结论 引言 InheritedWidget,flutter中非常重要的一个功能组件.比如我们在应用的根 widget 中通过InheritedWidget共享了一个数据,那么我们便可以在任意子 widget 中来获取该共享的数据. didChangeDependencies 说到 InheritedWidget ,我们不得不聊聊 state 对象中的 didChangeDependencies 方法.当子控件依赖使用了父控件中的

  • Flutter Widgets粘合剂CustomScrollView NestedScrollView滚动控件

    目录 概述: CustomScrollView 相互嵌套场景 NestedScrollView 滚动隐藏AppBar SliverAppBar展开折叠 与TabBar配合使用 总结: 概述: Flutter中常用的滑动布局 ScrollView 有 SingleChildScrollView.NestedScrollView.CustomScrollView. SingleChildScrollView 用来处理简单可滑动的页面布局视图,如一般的数据详情页面,当内容足够多时,一屏显示不下时,就需

  • Flutter Widget 之StatefulBuilder构建方法详解

    目录 正文 性能问题解决 正文 你曾否意识到你需要拆分一个大型的构建方法,但又觉得这听起来很费劲? 试试StatefulBuilder 以最小的代价获得一个个单独的小部件的所有性能 想象一下,这样的一个小部件,有一个可以切换单一标志的便宜的子部件,然后是一个昂贵的小部件. 除非绝对必要,否则你不会想要重建它 bool isExpanded = false; Widget build(context) { return Column( children: [ InexpendsiveStatefu

  • Flutter开发Widgets 之 PageView使用示例

    目录 构造方法以及参数: 基本用法 无限滚动 实现指示器 切换动画 总结: 构造方法以及参数: PageView可用于Widget的整屏滑动切换,如当代常用的短视频APP中的上下滑动切换的功能,也可用于横向页面的切换,如APP第一次安装时的引导页面,也可用于开发轮播图功能. PageView({ Key? key, this.scrollDirection = Axis.horizontal, // 设置滚动方向 垂直 / 水平 this.reverse = false, // 反向滚动 Pag

  • Flutter Widgets之标签类控件Chip详解

    目录 概述: RawChip Chip InputChip ChoiceChip FilterChip 总结: 概述: Flutter 标签类控件大全ChipFlutter内置了多个标签类控件,但本质上它们都是同一个控件,只不过是属性参数不同而已,在学习的过程中可以将其放在放在一起学习,方便记忆. RawChip Material风格标签控件,此控件是其他标签控件的基类,通常情况下,不会直接创建此控件,而是使用如下控件: Chip InputChip ChoiceChip FilterChip

  • Flutter Widget 之FocusableActionDetector使用详解

    目录 Material按钮 GestureDetector自定义按钮 为按钮添加一些条件性的样式 Material按钮 Material按钮会很好 但我们知道它们不一定适合你的应用程序,所以你要自己编写.可悲的是,从头开始编写自己的空间可能是一项艰巨的工作. 桌面用户期待悬停高亮.焦点和键盘快捷键,这是很难做好的. GestureDetector自定义按钮 是这样的,你在你的应用程序中创建一个自定义的按钮, 使用GestureDetector,当你点击它的时候,按钮会做一些事情 GestureD

  • Flutter Widgets MediaQuery控件屏幕信息适配

    目录 MediaQuery MediaQueryData 使用场景 根据尺寸构建不同的布局 系统字体变化 第三方屏幕的适配框架: 设置字体不随系统字体大小进行改变 APP全局 总结: MediaQuery 通常情况下,不会直接将MediaQuery当作一个控件,而是使用MediaQuery.of获取当前设备的信息,用法如下: var data = MediaQuery.of(context); 此方式必须放在MediaQuery作用域内,否则会抛出异常,MaterialApp和WidgetsAp

  • C++获得其他程序窗体控件中信息的方法

    本文实例讲述了C++获得其他程序窗体控件中信息的方法.分享给大家供大家参考.具体分析如下: 这里演示了获得其他程序窗体控件信息的方法, 用FindWindow API找到文本框句柄,用SendMessage(WM_GETTEXT)获得文本 #include <windows.h> BOOL CALLBACK EnumChildProc(HWND hWnd,LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrev

  • 在ASP.NET 2.0中操作数据之十九:给编辑和新增界面增加验证控件

    导言 在前面三节的示例中,GridView和DetailsView控件使用的是绑定列和CheckBoxField(绑定GridView和DetailsView时,通过智能标记可以令VS根据数据库自动增加对应的类型).当编辑GridView或者DetailsView中的一行时,非只读属性的绑定列将自动转为textbox,以便用户修改现有的数据.同样地,当在DetailsView控件中新增记录时,InsertVisible属性为true(默认值)的绑定列会呈现出空的textbox,以接受用户输入.C

  • GridView控件实现数据的显示和删除(第8节)

    本节的学习内容是新闻列表的实现,使用分页功能一个页面显示4条新闻.在新闻显示页面,添加一个字段"删除",运行时,单击该行的"删除按钮时",弹出"确认删除此信息?"的提示信息,当按确定按钮时删除该行的信息,按取消按钮时不执行删除操作. 首先我们先进行一个知识点归纳: 数据源控件:用于实现从不同数据源获取数据的功能,可以设置连接信息.查询信息.参数和行为,可以消除ASP.NET中要求的大量的重复性代码. 数据绑定控件:只负责管理与实际数据存储源的连接

  • 激活 ActiveX 控件

    激活 ActiveX 控件 发布日期: 2006-3-29 | 更新日期: 2006-3-29 Internet 开发索引 用户不能与 APPLET.EMBED 或 OBJECT 元素加载的 Microsoft ActiveX 控件直接交互.用户激活这些控件的用户界面后才可以与这些控件交互.本文介绍 Microsoft Internet Explorer 如何处理 ActiveX 控件,显示如何加载 ActiveX 控件才能激活它们的界面,还描述这种行为对辅助工具和宿主 WebBrowser 控

  • android实现图片验证码方法解析(自绘控件)

    自绘控件的内容都是自己绘制出来的 大致流程如下: 1.定义一个类继承view 1.使用TypedArray初始化属性集合     在view的构造方法中 有一个AttributeSet的参数 很明显是用来保存控件属性信息的 我们也的确可以通过循环然后用键值对的方式获取信息 而TypedArray是用来简化我们的工作的 2.重写onMeasure 测量控件大小 3.重写onDraw 绘制控件 2.根据需求在attrs文件中自定义属性 declare-styleable 声明自定义属性可以自定义一个

  • 在ASP.NET 2.0中操作数据之三十九:在DataList的编辑界面里添加验证控件

    导言 到目前为止的讨论编辑DataList的教程里,没有包含任何验证用户的输入,即使是用户非法输入- 遗漏了product的name或者负的price- 会导致异常.在前面一章里我们学习了如何在DataList的UpdateCommand事件处理中添加异常处理代码,以便在出现异常时捕捉它并显示友好的错误信息.然而理想的编辑界面应该包含验证控件,用来在第一时间里阻止用户输入一些非法数据. 本章我们将学习在DataList的EditItemTemplate里添加验证控件从而提供一个更安全的编辑界面,

  • GridView控件实现数据的修改(第9节)

    上一篇是使用GridView控件实现数据的显示和删除,这一节设计页面,使用GridView控件实现数据的更新操作,当更新时新闻的内容没有输入则提示"不能为空". 学习内容: 学习任务一 使用GridView控件实现信息的更新 步骤一:数据源控件定义数据的方法,在newschuli.cs页面中编写代码如下: public static void modifynews(newsclass news1) { using (SqlConnection cn = dbconn.GetConnec

  • 在ASP.NET 2.0中操作数据之五十:为GridView控件添加Checkbox

    导言: 在前面的教程里我们探讨了如何为GridView控件添加radio buttons列.当用户最多只能选择一项数据时,我们可以在用户界面里添加radio buttons列,而有时候,我们需要选择任意多项数据.比如,基于Web的邮箱客户端列出了一系列的邮件,及一列checkboxes,用户可选择任意封邮件并执行相同的操作,比如移动到另一个文件夹或将之删除. 在本教程,我们将探讨如何添加checkboxes列,以及发生页面回传后如何确定到底选择了哪些checkboxes.特别的,我们将练习一个类

随机推荐