天天看點

Flutter 94: 初識 MediaQuery

      當我們同時為手機和平闆适配編寫 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.removePadding() 删除視圖内邊距

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}');           
Flutter 94: 初識 MediaQuery

2. devicePixelRatio

      devicePixelRatio 為像素密度;與裝置實體像素有關,與橫豎屏等無關;

print('螢幕像素比 -> ${MediaQuery.of(context).devicePixelRatio}');           
Flutter 94: 初識 MediaQuery

3. orientation

      orientation 為橫豎屏,Orientation.landscape 為橫屏,Orientation.portrait 為豎屏;

print('橫豎屏 -> ${MediaQuery.of(context).orientation}');           
Flutter 94: 初識 MediaQuery

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}');           
Flutter 94: 初識 MediaQuery
Flutter 94: 初識 MediaQuery

5. platformBrightness

      platformBrightness 為目前裝置的亮度模式;注意調整螢幕亮度并不會改變該模式,與目前系統支援的黑暗模式和明亮模式相關;

print('亮度模式 -> ${MediaQuery.of(context).platformBrightness}');           
Flutter 94: 初識 MediaQuery

6. alwaysUse24HourFormat

      alwaysUse24HourFormat 為目前裝置是否為 24 小時制;

print('24 小時制 -> ${MediaQuery.of(context).alwaysUse24HourFormat}');           
Flutter 94: 初識 MediaQuery

7. accessibleNavigation

      accessibleNavigation 為是否使用 TalkBack 或 VoiceOver 之類的輔助功能與應用程式進行互動,用以輔助視力障礙人群;

print('亮度模式 -> ${MediaQuery.of(context).accessibleNavigation}');           
Flutter 94: 初識 MediaQuery

8. invertColors

      invertColors 為是否使用顔色反轉,主要用于 iOS 裝置;

print('顔色反轉 -> ${MediaQuery.of(context).invertColors}');           
Flutter 94: 初識 MediaQuery

9. highContrast

      highContrast 為使用者是否要求前景與背景之間的對比度高,主要用于 iOS 裝置;

print('前後背景高對比度 -> ${MediaQuery.of(context).highContrast}');           
Flutter 94: 初識 MediaQuery

10. disableAnimations

      disableAnimations 為平台是否要求禁用或減少動畫;

print('是否減少動畫 -> ${MediaQuery.of(context).disableAnimations}');           
Flutter 94: 初識 MediaQuery

11. boldText

      boldText 為平台是否要求使用粗體;

print('是否使用粗體 -> ${MediaQuery.of(context).boldText}');           
Flutter 94: 初識 MediaQuery

12. padding

      padding 為螢幕内邊距,一般是劉海兒屏或異形屏中被系統遮擋部分邊距;

print('内邊距 -> ${MediaQuery.of(context).padding}');           
Flutter 94: 初識 MediaQuery

13. viewInsets

      viewInsets 為鍵盤彈出時等遮擋螢幕邊距,其中 viewInsets.bottom 為鍵盤高度;

print('鍵盤遮擋内邊距 -> ${MediaQuery.of(context).viewInsets}');           
Flutter 94: 初識 MediaQuery

14. systemGestureInsets

      systemGestureInsets 為手勢邊距,如 Android Q 之後添加的向左滑動關閉頁面等;

print('系統手勢邊距 -> ${MediaQuery.of(context).systemGestureInsets}');           
Flutter 94: 初識 MediaQuery

15. viewPadding

      viewPadding 小菜了解為視圖内邊距,為螢幕被劉海兒屏或異形屏中被系統遮擋部分,從 MediaQuery 邊界的邊緣計算;此值是保持不變;例如,螢幕底部的軟體鍵盤可能會覆寫并占用需要底部填充的相同區域,是以不會影響此值;

print('系統手勢邊距 -> ${MediaQuery.of(context).systemGestureInsets}');           
Flutter 94: 初識 MediaQuery

16. physicalDepth

      physicalDepth 為裝置實體層級,小菜暫時還未想到對應的應用場景;

print('裝置實體層級 -> ${MediaQuery.of(context).physicalDepth}');           
Flutter 94: 初識 MediaQuery

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)))           
MediaQuery 案例嘗試

      小菜對于部分 MediaQueryData 的應用和了解還不夠深入;如有錯誤請多多指導!

來源: 阿策小和尚

繼續閱讀