Flutter Widgets MediaQuery控件屏幕信息适配
风雨_83 人气:0MediaQuery
通常情况下,不会直接将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
.
加载全部内容