前言:
這是我參與8月更文挑戰的第 19 天,活動詳情檢視:8月更文挑戰。為應掘金的八月更文挑戰
,我準備在本月挑選 31
個以前沒有介紹過的元件,進行全面分析和屬性介紹。這些文章將來會作為 Flutter 元件集錄
的重要素材。希望可以堅持下去,你的支援將是我最大的動力~
接下來的兩篇文章,將對 Flexible
、Expanded
和 Spacer
三個元件進行探討,包括使用及原始碼實現。
一、 認識 Flexible 元件
從原始碼中可以看出 Flexible
元件只能用於 Row
、Column
或 Flex
元件中。我們知道 Row
和Column
的本質也是 Flex
元件,在很久之前寫過 Flex
的使用文章。今天來看一下 Flex
元件的御用
周邊元件。Flexible
的作用是:使子元件可以靈活地填充主軸的可用空間
。
1.Flexible 基本資訊
Flexible
繼承自 ParentDataWidget<FlexParentData>
,這個型別的父元件可能大家都沒見過,畢竟我們很少自定義 ParentDataWidget
型別的元件。Flexible
構造中必須傳入 child 元件。另外還有兩個引數:int
型的 flex
,和 FlexFit
列舉型的 fit
。
可以說類的定義還是比較簡單的,下面一起看一下該元件的使用,及兩個屬性的作用。
2.Flexible 的使用
我們用如下的 Row
元件進行測試,外框是 Row
元件的區域,目前裡面只有一個頭像,佔位為深藍色區域。前面提到:Flexible
可使子元件可以靈活地填充主軸中的可用空間
。那麼這裡的可以空間就是 Row
除深藍色區域。
class FlexibleDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 200,
height: 54,
color: Colors.grey.withAlpha(11),
child: Row(
children:[
buildHead(),
],
),
);
}
Widget buildHead(){
return Padding(
padding: const EdgeInsets.all( 8.0),
child: Image.asset('assets/images/icon_head.png',width: 40,height: 40,),
);
}
}
複製程式碼
現在做個小測試,在 Row
裡新增一個藍色的 Container
,那麼會如何顯示。Container
元件的佔位又會是怎樣呢?
Row(
children:[
buildHead(),
Container(
color: Colors.blueAccent,
),
]
)
複製程式碼
可以看出在為 54
的 Row
中 Container
預設的約束為 [w(0,0) - h(0,54)]
。再加上 Container
在父區域內延展的特性,尺寸為 Size(0,54)
,也就是說它不可見。
當然,我們可以通過指定寬度來修改區域約束,讓 Container
顯示出來。但有個問題:如何讓 Container
填充剩餘的空間呢?
雖然我們可以通過計算剩餘尺寸來設定 Container
的寬,但是這個計算過程比較麻煩,特別是 Row 裡子元件非常多或不固定,用算的自然比較費勁。其實這些 Flutter 內部已經幫你做了,並暴露一個 Flexible
元件來給你用。我們只需要簡單地套一個 Flexible
即可。
Row(
children:[
buildHead(),
Flexible( //<--- 使用 Flexible
child: Container(
color: Colors.blueAccent,
),
),
],
)
複製程式碼
可以看出加上 Flexible
元件後,約束變成了 [w(0,144) - h(0,54)]
,其中 144
是框架內部幫我們計算出來的。我們只需要使用 Flexible
元件,不必考慮計算的細節,是不是很妙。
3.Flexible 的 flex 屬性作用
如果只有一個子元件套 Flexible
,那麼 flex
屬性設成什麼都是一樣的效果。當有多個 Flexible
元件時,會根據 flex
值 瓜分剩餘空間
,如下是 藍 3 紅 1
的效果。
Row(
children:[
buildHead(),
Flexible(
flex:3,
child: Container(
color: Colors.blueAccent,
),
),
Flexible(
flex: 1,
child: Container(
color: Colors.red,
),
)
],
),
複製程式碼
也就是藍色佔據剩餘寬度 (3/(3+1))
的百分比,剩餘寬是 144
,從樹中可以看出,第一個 Container
的寬確實是 108
。這樣多個 Flexible
元件時,根據 flex
屬性我們可以確定該元件在剩餘空間的佔比。
4.Flexible 的 fit 屬性作用
fit
是一個 FlexFit
型的列舉,只有兩個元素 tight
和 loss
,所以並不是很難。預設下是 loss
。
enum FlexFit {
tight,
loose,
}
複製程式碼
那 tight
和 loss
有什麼作用呢?我們通過之前的例子再看一下:如果 Flexible
包裹的子元件有固定的尺寸,預設情況下 loss
是無法使其區域延展的,甚至 Flexible
本身的尺寸也不會擴充套件。
Row(
children:[
buildHead(),
Flexible(
fit: FlexFit.loose,
child: Container(
width: 40,
color: Colors.blueAccent,
),
),
],
),
複製程式碼
當為 tight
時,Flexible
會強制 延展
。這就是兩者最大的區別。
Row(
children:[
buildHead(),
Flexible(
fit: FlexFit.tight,
child: Container(
width: 40,
color: Colors.blueAccent,
),
),
],
),
複製程式碼
可能 Container
自身的延展性上面的例子體現並不明顯。可以通過一個固定尺寸的 Icon
來說明一下:如下左側是 loose
,右側是 tight
。只要記住 tight
會強制延展自身區域即可。
二、Expanded 元件的實現
Expanded
的實現非常非常簡單,下面是它的全部程式碼。它就是繼承自 Flexible
元件,將 fit
值固定為 tight
而已,所以說 Expanded
就是一個強制延展的 Flexible
元件。
兩者在使用上並沒有什麼區別,由於 Flexible
可以設定 fit
值,所以用途要比 Expanded
廣泛。而強制延展的場景使用 Expanded
元件語義更好,而且簡單一點。
三、Spacer 元件的實現
Expanded
的實現也非常簡單,下面是它的全部程式碼。它是一個 StatelessWidget
,內部依賴 Expanded
元件實現功能,特點是:它不能設定子元件,本身作為空白佔位使用。
總的來說 Spacer
和 Expanded
的功能都基於 Flexible
元件實現。瞭解了 Flexible
元件的使用,就可以一通百通。那本文到這裡就結束了,謝謝觀看,明天見~