本文首發於公眾號「劉望舒」
ReactNative入門系列 React Native元件 Flutter基礎系列
前言
Flutter的佈局在此前的文章多多少少用過,但是沒有具體講過,Flutter的佈局實際上也由Widget來控制的,在Flutter官網上並沒有對佈局Widget進行分類,這裡將佈局Widget根據子元素排列方式分為以下幾種:
- 線性佈局Widget
- 流式佈局Widget
- 層式佈局Widget
- 彈性佈局Widget
下面分別介紹這幾種佈局Widget。
1.線性佈局Widget
線性佈局類似於Android中的LinearLayout,可以垂直也可以水平排列,Flutter的線性佈局有兩個:
- Row:水平方向的線性佈局。
- Column:垂直方向的線性佈局。
Row和Column的使用方法類似,舉個Row的例子,Column自然而然也就會了。
import 'package:flutter/material.dart';
void main() => runApp(RowWidget());
class RowWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Flutter",
home: Scaffold(
appBar: AppBar(
title: Text("Row示例"),
),
body: Padding(
padding: EdgeInsets.all(40.0),
child: Row(
children: <Widget>[
Text("Android進階之光"),
Text("Android進階解密"),
],
),
),
),
);
}
}
複製程式碼
效果如下圖所示。
2.流式佈局Widget
流式佈局就是把超出螢幕顯示範圍的控制元件自動換行,在Android中並沒有現成的流式佈局控制元件,都是開發人員自己封裝的,比如鴻洋封裝的FlowLayout。Flutter中提供了Wrap來實現流式佈局。
import 'package:flutter/material.dart';
void main() => runApp(ChipWidget());
class ChipWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Flutter",
home: Scaffold(
appBar: AppBar(
title: Text("流式佈局示例"),
),
body: Padding(
padding: EdgeInsets.all(20.0),
child: Wrap(
direction: Axis.horizontal, //主軸的方向
spacing: 8.0, // 主軸方向的間距
runSpacing: 12.0, // 交叉軸方向的間距
children: <Widget>[
Chip(//1
avatar: CircleAvatar(
backgroundColor: Colors.blue, child: Text('1')),
label: Text('Android進階之光'),
),
Chip(
avatar: CircleAvatar(
backgroundColor: Colors.blue, child: Text('2')),
label: Text('Android進階解密'),
),
Chip(
avatar: CircleAvatar(
backgroundColor: Colors.blue, child: Text('3')),
label: Text('Android進階?'),
),
],
),
),
),
);
}
}
複製程式碼
註釋1處的Chip意為碎片,實際上是一個標籤Widget,這個例子中定義了三個標籤來體現流式佈局。 Wrap有很多屬性,它的建構函式如下:
Wrap({
Key key,
this.direction = Axis.horizontal, //1
this.alignment = WrapAlignment.start,//2
this.spacing = 0.0,
this.runAlignment = WrapAlignment.start,
this.runSpacing = 0.0,
this.crossAxisAlignment = WrapCrossAlignment.start,
this.textDirection,
this.verticalDirection = VerticalDirection.down,
List<Widget> children = const <Widget>[],
}) : super(key: key, children: children);
複製程式碼
註釋1處的direction屬性,它用於設定主軸的方向(子Widget排列的方向),預設值為Axis.horizontal,部分屬性見下表:
引數名稱 | 引數型別 | 含義 |
---|---|---|
direction | Axis | 主軸的方向 |
alignment | WrapAlignment | 子Widget 在主軸上的對齊方式 |
runAlignment | WrapAlignment | 每行或每列的對齊方式 |
runSpacing | double | 每行或每列之間的間距 |
crossAxisAlignment | WrapCrossAlignment | 子Widget在交叉軸上的對齊方式 |
textDirection | TextDirection | 子Widget在主軸方向上的佈局順序 |
verticalDirection | VerticalDirection | 子Widget在交叉軸方向上的佈局順序 |
執行後的效果如下圖所示。
3.層式佈局Widget
層式佈局類似於Android的FrameLayout,在Flutter可以通過Stack來實現層式佈局,其子Widget 會按照新增順序確定顯示層級,後面新增的會覆蓋在前面新增的Widget上面。 為了確定子Widget到父容器四個角的位置,Stack將子Widget分為兩類:
- positioned:Positioned巢狀的子Widget,Positioned可以控制子Widget到父容器四個邊的距離。
- non-positioned :沒有用Positioned巢狀起來的子Widget,使用Stack的alignment屬性來控制自身在父容器裡的位置。
import 'package:flutter/material.dart';
void main() => runApp(StackWidget());
class StackWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Flutter",
home: Scaffold(
appBar: AppBar(
title: Text("層式佈局示例"),
),
body: Stack(
fit: StackFit.expand,
children: <Widget>[
Positioned(
left: 90.0,
top: 120.0,
child: Image.asset(
"images/decode.png",
width: 200.0,
fit: BoxFit.cover,
),
),
Container(
child: Text('Android進階三部曲第二部',
style: TextStyle(
color: Colors.lightBlue, fontSize: 20.0)),
height: 50.0,
width: 100.0,
alignment: Alignment.center,
)
],
),
),
);
}
}
複製程式碼
上面的程式碼中,Stack分為兩個部分,一個是Positioned Widget,用於顯示一個圖片,一個是non-positioned Widget,巢狀在Container中,用於顯示一行文字。效果如下圖所示。
4.彈性佈局Widget
Flutter中的彈性佈局是Flex,類似於Android中的FlexboxLayout。為了避免子Widget在Flex、Row、Column 中超界,可以使用Flexible和Expanded,它們可以讓Flex、Row、Column的子Widget具有彈效能力,下面以Flex和Expanded搭配使用作為例子。
import 'package:flutter/material.dart';
void main() => runApp(FlexWidget());
class FlexWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Flutter",
home: Scaffold(
appBar: AppBar(
title: Text("彈性佈局示例"),
),
body: Flex(
direction: Axis.horizontal,//1
children: <Widget>[
Expanded(
flex: 1,
child: Container(
height: 60.0,
width: 30.0,
color: Colors.red,
),
),
Expanded(
flex: 3,
child: Container(
height: 60.0,
width: 30.0,
color: Colors.yellow,
),
),
Expanded(
flex: 1,
child: Container(
height: 60.0,
width: 30.0,
color: Colors.blue,
),
),
],
),
),
);
}
}
複製程式碼
註釋1處的direction屬性,用於設定主軸的方向,這是必須要設定的。Flex的子Widget是三個Expanded,每個Expanded負責顯示一個矩形色塊,用flex來設定彈性係數,三個矩形色塊的比例為1:3:1,效果如下圖所示。
總結
本文介紹了Flutter中佈局Widget分類,實際上對於每個佈局分類都可以寫一篇文章,這裡都做了簡化,帶領大家快速入門。如果你想了解更多,可以檢視文件或者直接檢視各種Widget的原始碼。