佈局
The core of Flutter’s layout mechanism is widgets. In Flutter, almost everything is a widget—even layout models are widgets.
1、Column & Row & Flex
將Column、Row、Flex放在一小節是因為不同之處只是對子Widget佈局方式不同。Column垂直佈局子元件,Row是水平佈局子元件,Flex根據direction設定Axis.horizontal或是Axis.vertical。
Column(
children: <Widget>[
Text("text"),
Text("text"),
Text("text"),
],
);
Row(
children: <Widget>[
Text("text"),
Text("text"),
Text("text"),
],
);
Flex(
direction: Axis.vertical,
children: <Widget>[
Text("text"),
Text("text"),
Text("text"),
],
);
Flex(
direction: Axis.horizontal,
children: <Widget>[
Text("text"),
Text("text"),
Text("text"),
],
);
複製程式碼
另外元件都不支援滑動,一旦子元件較多超出可顯示範圍,在Debug模式下會出現warning提示錯誤。通常情況下一般是使用ListView而非Column去顯示列表,當然可以在Column、Row、Flex外層巢狀SingleChildScrollView使其支援滑動。
Tips
- Column和Row不支援對Padding,margin以及寬高的設定,一般外層巢狀Container或是Padding元件實現約束佈局寬度和間距。
- Expanded元件也是在Column和Row中經常使用,通過它對子元件進行權重大小劃分。類似於Android的XML佈局檔案中weight屬性,Expanded中有flex引數用於設定比重比例,數值越大比重越大。
- MainAxisAlignment屬性是與當前元件方向一致的軸,例如Row的主軸是水平方向,當設定MainAxisAlignment對於Row來說是在水平方向。支援的設定引數有:start、end、center、spaceBetween、spaceAround、spaceEvenly。詳見文件
- CrossAxisAlignment屬性是與當前元件方向成垂直的軸,例如Row的交叉軸就是垂直方向,當設定MainAxisAlignment對於Row來說是在垂直方向。支援的設定引數有:start、end、center、stretch、baseline詳見文件
- MainAxisSize屬性可設定:max、min,預設為max。類似於Android中math_content和wrap_content,當為min時大小根據子元件約束大小如果為max時大小根據自身約束大小。
- Column和Row繼承自Flex。個人理解在一些特定UI佈局中可以使用Flex,例如需要切換垂直和水平佈局的時候選用。
2、Expanded & Flexible
這節是彈性佈局,上節已經有提到Column和Row使用子元件時通過巢狀彈性佈局Expanded重來分配佈局空間,同時也說過Flutter中彈性佈局類似於Android中XML的weight屬性。可知Expanded元件繼承自Flexible,唯獨不同的是Flexible的fit屬性值預設FlexFit.loose並且可設定,Expanded的fit屬性值是FlexFit.tight並且不能設定。
Flexible
class Flexible extends ParentDataWidget<Flex> {
/// Creates a widget that controls how a child of a [Row], [Column], or [Flex]
/// flexes.
const Flexible({
Key key,
this.flex = 1,
this.fit = FlexFit.loose,
@required Widget child,
}) : super(key: key, child: child);
複製程式碼
Expanded
const Expanded({
Key key,
int flex = 1,
@required Widget child,
}) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);
複製程式碼
FlexFit屬性:tight、loose。tight會讓子元件強制填充可用最大布局空間;loose會讓子元件儘可能填充可用佈局空間。字面上的意思tight比loose更強烈,如下例項設定tight比起loose會佔用更多佈局空間,而loose會根據巢狀的元件而定是否根據比重填充更多空間。
Column(
children: <Widget>[
Flexible(
flex: 2,
child: Container(
color: Colors.blue,
child: Center(
child: Text(
"Flexible 2",
style: TextStyle(color: Colors.white),
),
),
),
),
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Container(
child: Text(
"Flexible 1 FlexFit.tight",
),
),
),
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Container(
child: Text(
"Flexible 1 FlexFit.tight",
),
),
),
Center(
child: Text(
"NO Flexible",
),
),
],
);
複製程式碼
Tips
- 例如Flexible內部巢狀了Center元件即便FlexFit是loose元件填充空間還是會按照比重獲取對應比例的大小。而沒有內部沒有巢狀Center元件的Flexible則沒有按照比重填充空間而是根據自身元件實際大小填充。詳見文件
- Spacer是一個空元件,主要用於填充空白區域,預設flex為1。
- Flexible可以解決在Column和Row設定子元件Text的文字超出範圍警告問題。原先以為使用Text屬性overflow: TextOverflow.ellipsis可以解決但實際情況不可行。其實只需要在Text外層巢狀Flexible並能解決。