當我們同時為手機和平板適配編寫 app 針對不同螢幕尺寸進行 UI 佈局或當使用者偏好設定較大字號或是想要最大限度等減少動畫等;此時就需要 MediaQuery 來幫我們獲取所用裝置的資訊以及使用者設定的偏好資訊;
MediaQuery
MediaQuery 一直存在於 WidgetsApp 和 MaterialApp 中,MediaQuery 繼承自 InheritedWidget 是一個單獨的 Widget,但一般通過 MediaQuery.of(context) 來獲取相關資訊;
當相關資訊發生變化,例如螢幕旋轉等時,螢幕中 Widget 會重新構建,以保持最新狀態;我們可以通過 MediaQuery 建構函式和提供的靜態方法手動設定對應的相關資訊;
1. MediaQuery()
const MediaQuery({
Key key,
@required this.data,
@required Widget child,
})
複製程式碼
2. MediaQuery.removePadding() 刪除內邊距
factory MediaQuery.removePadding({
Key key,
@required BuildContext context,
bool removeLeft = false,
bool removeTop = false,
bool removeRight = false,
bool removeBottom = false,
@required Widget child,
})
複製程式碼
3. MediaQuery.removeViewInsets() 刪除檢視內邊距
factory MediaQuery.removeViewInsets({
Key key,
@required BuildContext context,
bool removeLeft = false,
bool removeTop = false,
bool removeRight = false,
bool removeBottom = false,
@required Widget child,
})
複製程式碼
MediaQueryData
MediaQueryData 包含關於媒介的相關資訊;一般通過 MediaQuery.of(context) 獲取;
const MediaQueryData({
this.size = Size.zero,
this.devicePixelRatio = 1.0,
this.textScaleFactor = 1.0,
this.platformBrightness = Brightness.light,
this.padding = EdgeInsets.zero,
this.viewInsets = EdgeInsets.zero,
this.systemGestureInsets = EdgeInsets.zero,
this.viewPadding = EdgeInsets.zero,
this.physicalDepth = double.maxFinite,
this.alwaysUse24HourFormat = false,
this.accessibleNavigation = false,
this.invertColors = false,
this.highContrast = false,
this.disableAnimations = false,
this.boldText = false,
});
複製程式碼
1. size
size 為媒介的尺寸大小,以邏輯畫素為單位;
print('螢幕 Size -> ${MediaQuery.of(context).size}');
print('按鈕 Size -> ${_itemExpandedKey.currentContext.size}');
print('文字 Size -> ${_itemTextKey.currentContext.size}');
print('文字 Size -> ${MediaQuery.of(_itemTextKey.currentContext).size}');
複製程式碼
2. devicePixelRatio
devicePixelRatio 為畫素密度;與裝置物理畫素有關,與橫豎屏等無關;
print('螢幕畫素比 -> ${MediaQuery.of(context).devicePixelRatio}');
複製程式碼
3. orientation
orientation 為橫豎屏,Orientation.landscape 為橫屏,Orientation.portrait 為豎屏;
print('橫豎屏 -> ${MediaQuery.of(context).orientation}');
複製程式碼
4. textScaleFactor
textScaleFactor 為 每個邏輯畫素的字型畫素數,小菜理解為字型的畫素比;注意,小菜設定了預設字型畫素密度為標準的 1.2 倍之後調整裝置系統字號,其 1.2 倍依舊是以標準字號為基礎擴大 1.2 倍;
print('字型畫素比 -> ${MediaQuery.of(context).textScaleFactor}');
MediaQuery(data: MediaQuery.of(context).copyWith(textScaleFactor: 1.2),
child: Text('字型畫素比 * 1.2', style: TextStyle(color: Colors.white, fontSize: 16.0));
print('字型畫素比 * 1.2 -> ${MediaQuery.of(context).copyWith(textScaleFactor: 1.2).textScaleFactor}');
複製程式碼
5. platformBrightness
platformBrightness 為當前裝置的亮度模式;注意調整螢幕亮度並不會改變該模式,與當前系統支援的黑暗模式和明亮模式相關;
print('亮度模式 -> ${MediaQuery.of(context).platformBrightness}');
複製程式碼
6. alwaysUse24HourFormat
alwaysUse24HourFormat 為當前裝置是否為 24 小時制;
print('24 小時制 -> ${MediaQuery.of(context).alwaysUse24HourFormat}');
複製程式碼
7. accessibleNavigation
accessibleNavigation 為是否使用 TalkBack 或 VoiceOver 之類的輔助功能與應用程式進行互動,用以輔助視力障礙人群;
print('亮度模式 -> ${MediaQuery.of(context).accessibleNavigation}');
複製程式碼
8. invertColors
invertColors 為是否使用顏色反轉,主要用於 iOS 裝置;
print('顏色反轉 -> ${MediaQuery.of(context).invertColors}');
複製程式碼
9. highContrast
highContrast 為使用者是否要求前景與背景之間的對比度高,主要用於 iOS 裝置;
print('前後背景高對比度 -> ${MediaQuery.of(context).highContrast}');
複製程式碼
10. disableAnimations
disableAnimations 為平臺是否要求禁用或減少動畫;
print('是否減少動畫 -> ${MediaQuery.of(context).disableAnimations}');
複製程式碼
11. boldText
boldText 為平臺是否要求使用粗體;
print('是否使用粗體 -> ${MediaQuery.of(context).boldText}');
複製程式碼
12. padding
padding 為螢幕內邊距,一般是劉海兒屏或異形屏中被系統遮擋部分邊距;
print('內邊距 -> ${MediaQuery.of(context).padding}');
複製程式碼
13. viewInsets
viewInsets 為鍵盤彈出時等遮擋螢幕邊距,其中 viewInsets.bottom 為鍵盤高度;
print('鍵盤遮擋內邊距 -> ${MediaQuery.of(context).viewInsets}');
複製程式碼
14. systemGestureInsets
systemGestureInsets 為手勢邊距,如 Android Q 之後新增的向左滑動關閉頁面等;
print('系統手勢邊距 -> ${MediaQuery.of(context).systemGestureInsets}');
複製程式碼
15. viewPadding
viewPadding 小菜理解為檢視內邊距,為螢幕被劉海兒屏或異形屏中被系統遮擋部分,從 MediaQuery 邊界的邊緣計算;此值是保持不變;例如,螢幕底部的軟體鍵盤可能會覆蓋並佔用需要底部填充的相同區域,因此不會影響此值;
print('系統手勢邊距 -> ${MediaQuery.of(context).systemGestureInsets}');
複製程式碼
16. physicalDepth
physicalDepth 為裝置物理層級,小菜暫時還未想到對應的應用場景;
print('裝置物理層級 -> ${MediaQuery.of(context).physicalDepth}');
複製程式碼
Tips
小菜在嘗試獲取其他子 Widget Size 時,有兩點需要注意,首先要設定一個全域性的 GlobalKey 來獲取當前位置,key 需要為唯一的;第二通過 GlobalKey().currentContext 獲取 BuildContext 上下文環境,從而獲取對應尺寸;
var _itemExpandedKey = GlobalKey();
var _itemTextKey = GlobalKey();
Expanded(
key: _itemExpandedKey,
child: FlatButton(
onPressed: () => _itemClick(2),
child: Center(child: Text('按鈕 Size', key: _itemTextKey, style: TextStyle(color: Colors.white, fontSize: 16.0))),
color: Colors.purpleAccent.withOpacity(0.4)))
複製程式碼
小菜對於部分 MediaQueryData 的應用和理解還不夠深入;如有錯誤請多多指導!
來源: 阿策小和尚