目錄
- 簡介
- MediaQuery詳解
- MediaQuery的屬性
- MediaQuery的構造函數
- MediaQuery的使用
- 總結
簡介
移動的開發中,大家可能最頭疼的就是不同裝置的規格了,現在裝置這麼多,如何才能在諸多的裝置中找到合适的widget的位置來進行繪制呢?
不用怕,在flutter中為我們提供了一個叫做MediaQuery的利器,大家一起來看看吧。
MediaQuery詳解
MediaQuery從名字上來看,它的意思是媒體查詢。它可以查詢的東西就多了,可以查詢目前你app的視窗資訊,查詢你指定的某個widget的資訊等等,非常的強大。
我們先來看下MediaQuery到底是什麼。 具體來說MediaQuery繼承自InheritedWidget:
class MediaQuery extends InheritedWidget
那麼什麼是InheritedWidget呢?為什麼MediaQuery需要繼承InheritedWidget呢?
很多時候,我們需要從widget的子widget中擷取到父widget對象,InheritedWidget就是一個可以提供簡單擷取方法的對象。
在InheritedWidget中可以實作of方法,通過調用BuildContext.dependOnInheritedWidgetOfExactType來從context中擷取最臨近的InheritedWidget對象。
這裡,因為MediaQuery是一個媒體查詢工具,是以我們可能需要在很多地方随時随地的進行對象的擷取,那麼這裡使用InheritedWidget就是再好不過了。
MediaQuery的屬性
MediaQuery的自有屬性隻有兩個,分别是MediaQueryData類型的data和Widget類型的child。
MediaQueryData是一個類似于結構體的類,用來存儲各種Media的狀态資訊。
我們先來看下MediaQueryData的構造函數:
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.alwaysUse24HourFormat = false,
this.accessibleNavigation = false,
this.invertColors = false,
this.highContrast = false,
this.disableAnimations = false,
this.boldText = false,
this.navigationMode = NavigationMode.traditional,
})
可以看到,MediaQueryData中包含了很多有用的屬性,我們來詳細看一下具體的内容。
首先是表示media logical pixels大小的size。大家要注意的是,這裡的size表示的是邏輯pixels的大小。
有logical pixels,就有Physical pixels,前者表示的邏輯大小,在任何裝置上都是一樣的,而後者表示的是真實的實體裝置所支援的像素大小。這兩種是可以不同的。一個實體像素可能代表多個邏輯像素,這個對應關系就是由devicePixelRatio這個屬性來決定的。
devicePixelRatio表示的是一個實體像素代表多少個邏輯像素。devicePixelRatio并不要求是整數,比如在Nexus 6中,這個devicePixelRatio=3.5。
接下來是textScaleFactor,表示一個邏輯像素能夠表示多少個字型像素。或者你可以将其了解為字型的放大程度。
比如textScaleFactor=1.5,那麼它的意思是呈現出來的字型要比給定的字型大50%。
然後是platformBrightness,表示的是裝置的明亮程度。最常見的比如說明亮模式或者黑暗模式等。
viewInsets指的是被系統UI所完全遮罩的部分,比如說我們在進行鍵盤輸入的時候,會彈起鍵盤界面。
padding表示的是被系統UI所部分遮罩,并不能完全看見的部分,通常是系統狀态欄,比如iphone中的劉海等。
viewPadding表示的是被系統UI所部分遮罩,并不能完全看見的部分,通常是系統狀态欄,比如iphone中的劉海等。
哇喔,看起來padding和viewPadding是一樣的,那麼事實是否如此呢?
這兩者通常情況下是一樣的,隻有在出現鍵盤輸入界面的時候兩者就會發生不同。
簡單來說,viewPadding是固定的,它的大小不會随鍵盤的顯示而發生變化,Padding是可變化的,當鍵盤彈起,系統狀态欄被遮罩的時候,它的bottom值就是0。
systemGestureInsets是一個特殊的手勢區域,在這個區域裡面隻能識别部分的手勢指令,而不能識别所有的手勢指令,是以需要這樣的一個屬性。
alwaysUse24HourFormat表示是否使用24小時的時間格式。
accessibleNavigation表示使用者是否使用了一些accessibility服務來和應用進行互動。
還有其他的一些屬性比如highContrast,disableAnimations,boldText,navigationMode和orientation等基礎的屬性可以使用。
MediaQuery的另外一個屬性就是child了。
MediaQuery的構造函數
MediaQuery除了最正常的構造函數之外,還有三個構造函數,分别是MediaQuery.removePadding,MediaQuery.removeViewInsets和MediaQuery.removeViewPadding。
這三個構造函數都是通過傳入一個指定的context和child來構造MediaQuery,但是他們都相應的移出了一些屬性。根據名字就可以看出來,這三個分别移出的是padding,viewInsets和viewPadding。
我們以removePadding為例,看一下具體的實作流程:
factory MediaQuery.removePadding({
Key? key,
required BuildContext context,
bool removeLeft = false,
bool removeTop = false,
bool removeRight = false,
bool removeBottom = false,
required Widget child,
}) {
return MediaQuery(
key: key,
data: MediaQuery.of(context).removePadding(
removeLeft: removeLeft,
removeTop: removeTop,
removeRight: removeRight,
removeBottom: removeBottom,
),
child: child,
);
}
removePadding方法需要傳入四個額外的參數來表示是否需要移出padding的left,top,right或者bottom。
我們可以看到傳回了一個新的MediaQuery,其中data部分使用了
MediaQuery.of(context)
來擷取context最近的MediaQuery,然後調用它的removePadding方法将對應的padding屬性删除。
MediaQuery的使用
講完MediaQuery的構造函數,接下來我們看一下MediaQuery常用的使用場景。
其實MediaQuery最常見的用處就是來判斷裝置的大小,進而根據不同裝置的大小來進行頁面的調整。
比如下面的getSize方法:
enum ScreenSize { Small, Normal, Large, ExtraLarge }
ScreenSize getSize(BuildContext context) {
double deviceWidth = MediaQuery.of(context).size.shortestSide;
if (deviceWidth > 900) return ScreenSize.ExtraLarge;
if (deviceWidth > 600) return ScreenSize.Large;
if (deviceWidth > 300) return ScreenSize.Normal;
return ScreenSize.Small;
}
我們通過
MediaQuery.of(context)
拿到MediaQuery,然後通過size的shortestSide屬性獲得裝置的寬度,然後根據裝置的寬度跟特定的寬度進行對比,進而判斷裝置螢幕的大小。
當然,MediaQuery還可以用在其他需要檢測Media屬性的地方,大家可以仔細體會。
總結
MediaQuery是flutter中一個非常友善的工具,用來檢測media的屬性情況,根據MediaQuery,我們可以做出更加富有互動性的APP。
最通俗的解讀,最深刻的幹貨,最簡潔的教程,衆多你不知道的小技巧等你來發現!