注意:無特殊說明,Flutter版本及Dart版本如下:
- Flutter版本: 1.12.13+hotfix.5
- Dart版本: 2.7.0
Expanded和Flexible是控制Row、Column、Flex的子控件如何佈局的控件,Expanded和Flexible可以擴張填滿主軸剩餘空間,如何確認主軸和交叉軸可以查看Flutter Widgets 之 Row和Column,這篇文章詳細介紹了主軸和交叉軸。
Expanded和Flexible的區別
首先看一下Expanded和Flexible的構造函數:
區別如下
- Expanded 繼承自Flexible。
- Flexible 中
fit
參數默認是FlexFit.loose
,而Expanded固定爲FlexFit.tight
。
因此如果在使用Flexible時,設置fit
爲FlexFit.tight
,Flexible和Expanded就一模一樣了,代碼如下:
Flexible(
fit: FlexFit.tight,
...
)
因此Expanded和Flexible的區別就是FlexFit.tight
和FlexFit.loose
的區別:
- tight:必須(強制)填滿剩餘空間。
- loose:儘可能大的填滿剩餘空間,但是可以不填滿。
看下面2個例子就能看出其中的區別:
Row(
children: <Widget>[
Container(
color: Colors.blue,
height: 50,
width: 100,
),
Flexible(
child: Container(
color: Colors.red,
height: 50,
)
),
Container(
color: Colors.blue,
height: 50,
width: 100,
),
],
)
效果如圖:
中間的紅色的控件是Container,此時填滿了剩餘空間,我們給Container添加子控件Text,代碼如下:
Row(
children: <Widget>[
Container(
color: Colors.blue,
height: 50,
width: 100,
),
Flexible(
child: Container(
color: Colors.red,
height: 50,
child: Text('Container',style: TextStyle(color: Colors.white),),
)
),
Container(
color: Colors.blue,
height: 50,
width: 100,
),
],
)
效果圖:
神奇出現了,此時沒有填滿剩餘空間,我們再給Container添加對齊方式,代碼如下:
Row(
children: <Widget>[
Container(
color: Colors.blue,
height: 50,
width: 100,
),
Flexible(
child: Container(
color: Colors.red,
height: 50,
alignment: Alignment.center,
child: Text('Container',style: TextStyle(color: Colors.white),),
)
),
Container(
color: Colors.blue,
height: 50,
width: 100,
),
],
)
效果圖:
此時又填滿剩餘空間,大家是否還記得Container控件的大小是調整的嗎?Container默認是適配子控件大小的,但當設置對齊方式時Container將會填滿父控件,在Flutter Widgets 之 Container中已經詳細介紹,因此是否填滿剩餘空間取決於子控件是否需要填滿父控件。
如果把Flexible中子控件由Container改爲OutlineButton,代碼如下:
Row(
children: <Widget>[
Container(
color: Colors.blue,
height: 50,
width: 100,
),
Flexible(
child: OutlineButton(
child: Text('OutlineButton'),
),
),
Container(
color: Colors.blue,
height: 50,
width: 100,
),
],
)
OutlineButton正常情況下是不充滿父控件的,因此最終的效果應該是不填滿剩餘空間,效果如圖:
如果想讓OutlineButton填滿剩餘空間只需將Flexible改爲Expanded,代碼如下:
Row(
children: <Widget>[
Container(
color: Colors.blue,
height: 50,
width: 100,
),
Expanded(
child: OutlineButton(
child: Text('OutlineButton'),
),
),
Container(
color: Colors.blue,
height: 50,
width: 100,
),
],
)
效果如圖:
到這裏有沒有感覺FlexFit.loose
很雞肋啊,如果不想填滿剩餘空間直接不使用這個組件不就可以了嗎,既然使用Expanded
和Flexible
就說明想填滿剩餘空間,可能是我們的需求還沒有那麼變態吧。
建議:如果想填滿剩餘空間直接使用Expanded
更方便。
這裏總結下Expanded和Flexible的區別:
- Expanded:強制填滿剩餘空間
- Flexible:不強制填滿剩餘空間,是否填滿剩餘空間取決於子控件是否需要填滿父控件。
flex
參數flex
表示權重(類似於Android中的weight),在Column中添加3個子控件,flex分別爲1、2、3,代碼如下:
Column(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
color: Colors.blue,
alignment: Alignment.center,
child: Text('1 Flex/ 6 Total',style: TextStyle(color: Colors.white),),
),
),
Expanded(
flex: 2,
child: Container(
color: Colors.red,
alignment: Alignment.center,
child: Text('2 Flex/ 6 Total',style: TextStyle(color: Colors.white),),
),
),
Expanded(
flex: 3,
child: Container(
color: Colors.green,
alignment: Alignment.center,
child: Text('3 Flex/ 6 Total',style: TextStyle(color: Colors.white),),
),
),
],
)
效果如圖:
子控件佔比 = 當前子控件flex/所有子控件flex只和。
更多相關閱讀:
- Flutter系列文章總覽
- Flutter Widgets 之 Container
- Flutter Widgets 之 AnimatedList
- Flutter Widgets 之 SliverAppBar