Flutter Widgets MediaQuery控件屏幕信息適配
MediaQuery
通常情況下,不會直接將MediaQuery當(dāng)作一個控件,而是使用MediaQuery.of
獲取當(dāng)前設(shè)備的信息,用法如下:
var data = MediaQuery.of(context);
此方式必須放在MediaQuery作用域內(nèi),否則會拋出異常,MaterialApp和WidgetsApp都引入了MediaQuery,并且隨著屏幕的變化而導(dǎo)致重建,比如旋轉(zhuǎn)屏幕、彈出輸入框等。
MediaQueryData
MediaQueryData是MediaQuery.of
獲取數(shù)據(jù)的類型。說明如下:
屬性 | 說明 |
---|---|
size | 邏輯像素,并不是物理像素,類似于Android中的dp,邏輯像素會在不同大小的手機(jī)上顯示的大小基本一樣,物理像素 = size*devicePixelRatio。 |
devicePixelRatio | 單位邏輯像素的物理像素數(shù)量,即設(shè)備像素比。 |
textScaleFactor | 單位邏輯像素字體像素數(shù),如果設(shè)置為1.5則比指定的字體大50%。 |
platformBrightness | 當(dāng)前設(shè)備的亮度模式,比如在Android Pie手機(jī)上進(jìn)入省電模式,所有的App將會使用深色(dark)模式繪制。 |
viewInsets | 被系統(tǒng)遮擋的部分,通常指鍵盤,彈出鍵盤,viewInsets.bottom表示鍵盤的高度。 |
padding | 被系統(tǒng)遮擋的部分,通常指“劉海屏”或者系統(tǒng)狀態(tài)欄。 |
viewPadding | 被系統(tǒng)遮擋的部分,通常指“劉海屏”或者系統(tǒng)狀態(tài)欄,此值獨立于padding和viewInsets,它們的值從MediaQuery控件邊界的邊緣開始測量。在移動設(shè)備上,通常是全屏。 |
systemGestureInsets | 顯示屏邊緣上系統(tǒng)“消耗”的區(qū)域輸入事件,并阻止將這些事件傳遞給應(yīng)用。比如在Android Q手勢滑動用于頁面導(dǎo)航(ios也一樣),比如左滑退出當(dāng)前頁面。 |
physicalDepth | 設(shè)備的最大深度,類似于三維空間的Z軸。 |
alwaysUse24HourFormat | 是否是24小時制。 |
accessibleNavigation | 用戶是否使用諸如TalkBack或VoiceOver之類的輔助功能與應(yīng)用程序進(jìn)行交互,用于幫助視力有障礙的人進(jìn)行使用。 |
invertColors | 是否支持顏色反轉(zhuǎn)。 |
highContrast | 用戶是否要求前景與背景之間的對比度高, iOS上,方法是通過“設(shè)置”->“輔助功能”->“增加對比度”。此標(biāo)志僅在運行iOS 13的iOS設(shè)備上更新或以上。 |
disableAnimations | 平臺是否要求盡可能禁用或減少動畫。 |
boldText | 平臺是否要求使用粗體。 |
orientation | 是橫屏還是豎屏。 |
獲取設(shè)備相關(guān)信息:
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; //設(shè)備像素 double width = mSize.width * mRatio; double height = mSize.height * mRatio; // 上下邊距 (主要用于 劉海 和 內(nèi)置導(dǎo)航鍵) 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('設(shè)備像素大小:${width} x ${height}'), Text('上邊劉海:${topPadding}'), Text('下邊導(dǎo)航:${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}'), ], ),); } }
運行效果:
隨著屏幕旋轉(zhuǎn),設(shè)備信息跟著屏幕方向在變動。
使用場景
根據(jù)尺寸構(gòu)建不同的布局
SafeArea控件就是通過MediaQuery.of
來實現(xiàn)的,平板和手機(jī)的(或者橫屏和豎屏)布局可能是不一樣的,布局判斷:
var screenSize = MediaQuery.of(context).size; if(screenSize.width>oneColumnLayout){ //平板布局 }else{ //手機(jī)布局 }
oneColumnLayout
表示一列布局的寬度。
系統(tǒng)字體變化
很多App都有一個功能就是調(diào)節(jié)字體大小,通過MediaQuery來實現(xiàn),實現(xiàn)如下:
//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:用于調(diào)整屏幕和字體大小的顫振插件。讓你的UI在不同的屏幕尺寸上顯示合理的布局!
api適配:
ScreenUtil().setWidth(540) (dart sdk>=2.6 : 540.w) //根據(jù)屏幕寬度適配尺寸 ScreenUtil().setHeight(200) (dart sdk>=2.6 : 200.h) //根據(jù)屏幕高度適配尺寸(一般根據(jù)寬度適配即可) ScreenUtil().radius(200) (dart sdk>=2.6 : 200.r) //根據(jù)寬度或高度中的較小者進(jìn)行調(diào)整 ScreenUtil().setSp(24) (dart sdk>=2.6 : 24.sp) //適配字體 12.sm // 取12和12.sp中的最小值 ScreenUtil.pixelRatio //設(shè)備的像素密度 ScreenUtil.screenWidth (dart sdk>=2.6 : 1.sw) //設(shè)備寬度 ScreenUtil.screenHeight (dart sdk>=2.6 : 1.sh) //設(shè)備高度 ScreenUtil.bottomBarHeight //底部安全區(qū)距離,適用于全面屏下面有按鍵的 ScreenUtil.statusBarHeight //狀態(tài)欄高度 劉海屏?xí)? ScreenUtil.textScaleFactor //系統(tǒng)字體縮放比例 ScreenUtil().scaleWidth // 實際寬度設(shè)計稿寬度的比例 ScreenUtil().scaleHeight // 實際高度與設(shè)計稿高度度的比例 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的優(yōu)點 REdgeInsts.all(8) // EdgeInsets.all(8.r) EdgeInsets.only(left:8,right:8).r // EdgeInsets.only(left:8.r,right:8.r).
適配字體
//輸入字體大?。▎挝慌c初始化時的單位相同) ScreenUtil().setSp(28) 28.sp //例子: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( '16sp, 因為設(shè)置了`textScaleFactor`,不會隨系統(tǒng)變化.', style: TextStyle( color: Colors.black, fontSize: 16.sp, ), textScaleFactor: 1.0, ), Text( '16sp,如果未設(shè)置,我的字體大小將隨系統(tǒng)而變化.', style: TextStyle( color: Colors.black, fontSize: 16.sp, ), ), ], )
設(shè)置字體不隨系統(tǒng)字體大小進(jìn)行改變 APP全局
MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter_ScreenUtil', theme: ThemeData( primarySwatch: Colors.blue, ), builder: (context, widget) { return MediaQuery( ///設(shè)置文字大小不隨系統(tǒng)設(shè)置改變 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(), )
總結(jié):
本篇主要介紹了系統(tǒng)組價MediaQuery
的基本參數(shù)和基本使用情況,以及擴(kuò)展第三方屏幕適配組件flutter_screenutil
.
以上就是Flutter Widgets MediaQuery控件屏幕信息適配的詳細(xì)內(nèi)容,更多關(guān)于Flutter Widgets MediaQuery的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
IOS 中UIKit-UIPageControl利用delegate定位圓點位置
這篇文章主要介紹了IOS 中UIKit-UIPageControl利用delegate定位圓點位置 的相關(guān)資料,需要的朋友可以參考下2017-04-04iOS overFullScreen與fullScreen區(qū)別分析
這篇文章主要介紹了iOS overFullScreen與fullScreen區(qū)別分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11iOS中的導(dǎo)航欄UINavigationBar與工具欄UIToolBar要點解析
UINavigation可以附著于導(dǎo)航控制器之中使用,也可以在controller中單獨使用,這里我們將來看iOS中的導(dǎo)航欄UINavigationBar與工具欄UIToolBar要點解析.2016-06-06searchDisplayController 引起的數(shù)組越界處理辦法
這篇文章主要介紹了searchDisplayController 引起的數(shù)組越界處理辦法,需要的朋友可以參考下2015-07-07