Row
1、簡介
- Row元件是一個橫向排布的佈局元件,跟h5的Flex佈局一樣,只不過限定了橫向排布
2、建構函式
Row({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline textBaseline,
List<Widget> children = const <Widget>[],
})
複製程式碼
- mainAxisAlignment:主軸方向的排布方式,由於是橫向佈局,其主軸是橫向的水平線
- center:主軸中心
- start:主軸起點
- end:主軸末尾
- spaceAround:主軸中間空白區域均分,首尾空白區域為1/2
- spaceBetween:主軸中間空白區域均分,首尾沒有空白區域
- spaceEvenly:主軸中間空白區域均分,首尾平分空白區域
- mainAxisSize:主軸方向佔有空間的值
- max:佔用最大空間
- min:佔用最小空間
- crossAxisAlignment:側軸方向的排布方式,由於是橫向佈局,其側軸是垂直的豎線
- baseline:側軸與baseline對齊
- center:側軸居中顯示
- end:側軸末尾顯示
- start:側軸起點顯示
- stretch:側軸填滿顯示
- textDirection:文字的排布方式
- TextDirection.ltr:從左到右
- TextDirection.rtl:從右到左
- verticalDirection:子控制元件的排布方式
- down:從左上角到右下角進行佈局
- up:從右下角到左上角進行佈局
- textBaseline:文字的基準線
- children:子控制元件集合
3、例子
三個容器橫向排放
Widget _buildColumn() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
textDirection: TextDirection.ltr,
textBaseline: TextBaseline.alphabetic,
mainAxisSize: MainAxisSize.max,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Container(
height: 50,
width: 50,
color: Colors.blueAccent,
),
Container(
height: 50,
width: 50,
color: Colors.redAccent,
),
Container(
height: 50,
width: 50,
color: Colors.greenAccent,
)
],
);
}
複製程式碼
Column
1、簡介
- Column元件是一個豎向排布的佈局元件,跟h5的Flex佈局一樣,只不過限定了豎向排布
2、建構函式
Column({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline textBaseline,
List<Widget> children = const <Widget>[],
})
複製程式碼
- mainAxisAlignment:主軸方向的排布方式,由於是豎向佈局,其主軸是豎向的垂直線
- center:主軸中心
- start:主軸起點
- end:主軸末尾
- spaceAround:主軸中間空白區域均分,首尾空白區域為1/2
- spaceBetween:主軸中間空白區域均分,首尾沒有空白區域
- spaceEvenly:主軸中間空白區域均分,首尾平分空白區域
- mainAxisSize:主軸方向佔有空間的值
- max:佔用最大空間
- min:佔用最小空間
- crossAxisAlignment:側軸方向的排布方式,由於是豎向佈局,其側軸是橫向的水平線
- baseline:側軸與baseline對齊
- center:側軸居中顯示
- end:側軸末尾顯示
- start:側軸起點顯示
- stretch:側軸填滿顯示
- textDirection:文字的排布方式
- TextDirection.ltr:從左到右
- TextDirection.rtl:從右到左
- verticalDirection:子控制元件的排布方式
- down:從左上角到右下角進行佈局
- up:從右下角到左上角進行佈局
- textBaseline:文字的基準線
- children:子控制元件集合
3、例子
三個容器豎向排放,由於設定了up的擺放方式,導致位置是倒過來的
Widget _buildColumn() {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
verticalDirection: VerticalDirection.up,
textBaseline: TextBaseline.alphabetic,
textDirection: TextDirection.ltr,
children: <Widget>[Container(
height: 50,
width: 50,
color: Colors.blueAccent,
),
Container(
height: 50,
width: 50,
color: Colors.redAccent,
),
Container(
height: 50,
width: 50,
color: Colors.greenAccent,
)],
);
}
複製程式碼
Stack
1、簡介
- Stack元件是可以互相疊在一起的佈局,類似於一個棧
- Stack元件通過alignment去決定子控制元件的位置
2、建構函式
Stack({
Key key,
this.alignment = AlignmentDirectional.topStart,
this.textDirection,
this.fit = StackFit.loose,
this.overflow = Overflow.clip,
List<Widget> children = const <Widget>[],
})
複製程式碼
- alignment:控制child的對齊方式
- textDirection:文字的排布方式
- TextDirection.ltr:從左到右
- TextDirection.rtl:從右到左
- fit:定義子控制元件集合的尺寸
- StackFit.loose:子控制元件的尺寸不受限制
- StackFit.expand:子控制元件的尺寸儘可能大
- StackFit.passthrough:不改變子控制元件的約束條件
- overflow:超出佈局本身的處理
- Overflow.clip:超出的佈局被裁剪
- Overflow.visible:超出的佈局被顯示
- children:子控制元件集合
3、例子
將兩個容器疊加在一起,並且在對齊右下角
Widget _buildColumn() {
return Stack(
textDirection: TextDirection.ltr,
alignment: Alignment.bottomRight,
overflow: Overflow.visible,
fit: StackFit.loose,
children: <Widget>[
Container(
width: 100,
height: 100,
color: Colors.greenAccent,
),
Container(
height: 50,
width: 50,
color: Colors.redAccent,
)
],
);
}
複製程式碼
IndexedStack
1、簡介
- IndexedStack控制元件本質繼承了Stack元件,區別在於通過index增加了層級控制,控制層級的顯示
2、建構函式
IndexedStack({
Key key,
AlignmentGeometry alignment = AlignmentDirectional.topStart,
TextDirection textDirection,
StackFit sizing = StackFit.loose,
this.index = 0,
List<Widget> children = const <Widget>[],
})
複製程式碼
- alignment:控制child的對齊方式
- textDirection:文字的排布方式
- TextDirection.ltr:從左到右
- TextDirection.rtl:從右到左
- sizing:定義子控制元件集合的尺寸
- StackFit.loose:子控制元件的尺寸不受限制
- StackFit.expand:子控制元件的尺寸儘可能大
- StackFit.passthrough:不改變子控制元件的約束條件
- index:控制第幾個child的顯示,0表示第一個
- children:子控制元件集合
3、例子
通過index控制第二個容器的出現,第一個容器則隱藏
Widget _buildColumn() {
return IndexedStack(
index: 1,
sizing: StackFit.loose,
textDirection: TextDirection.ltr,
alignment: Alignment.bottomRight,
children: <Widget>[
Container(
width: 100,
height: 100,
color: Colors.greenAccent,
),
Container(
height: 50,
width: 50,
color: Colors.redAccent,
)
],
);
}
複製程式碼
Flow
1、簡介
- Flow控制元件相當於流式佈局,其佈局的擺佈方式任由開發者去控制
2、建構函式
Flow({
Key key,
@required this.delegate,
List<Widget> children = const <Widget>[],
})
複製程式碼
- delegate:佈局管理器,可以管理佈局的擺放
- children:子控制元件集合
3、例子
在Flow佈局中擺放一堆容器,並且大小不一
Widget _buildColumn() {
return Flow(
delegate: GridFlowDelegate(margin: EdgeInsets.all(10.0)),
children: <Widget>[
Container(
width: 100,
height: 100,
color: Colors.greenAccent,
),
Container(
height: 50,
width: 50,
color: Colors.redAccent,
),
Container(
width: 100,
height: 100,
color: Colors.greenAccent,
),
Container(
height: 50,
width: 50,
color: Colors.redAccent,
),
Container(
width: 100,
height: 100,
color: Colors.greenAccent,
),
Container(
height: 50,
width: 50,
color: Colors.redAccent,
),
Container(
width: 100,
height: 100,
color: Colors.greenAccent,
),
Container(
height: 50,
width: 50,
color: Colors.redAccent,
),
Container(
width: 100,
height: 100,
color: Colors.greenAccent,
)
],
);
}
複製程式碼
在佈局管理器中,自定義我們的擺佈方式,以一行中最高的容器作為換行的高度進行橫向擺佈
class GridFlowDelegate extends FlowDelegate {
EdgeInsets margin = EdgeInsets.zero;
GridFlowDelegate({this.margin});
@override
void paintChildren(FlowPaintingContext context) {
var x = margin.left; //繪製子控制元件的x座標
var y = margin.top; //繪製子控制元件的y座標
var maxHeightIndex = 0; //同一行中最大高度的子控制元件的索引,用於換行
for (int i = 0; i < context.childCount; i++) {
// 當前控制元件需要的最大寬度 = 控制元件本身的寬度 + 左右邊距
var w = context.getChildSize(i).width + x + margin.right;
if (w < context.size.width) {
// 如果未超出當前未分配的寬度,則直接平移到對應位置畫出來
context.paintChild(i, transform: Matrix4.translationValues(x, y, 0.0));
// 下一次的x座標
x = w + margin.left;
// 在第二個控制元件開始取同一行的最大高度的控制元件
if (i >= 1){
var currentHeight = context.getChildSize(i).height + margin.top + margin.bottom;
var lastHeight = context.getChildSize(maxHeightIndex).height + margin.top + margin.bottom;
if (currentHeight > lastHeight) {
// 保留最大高度的索引值
maxHeightIndex = i;
}
}
}else{
// 如果超出當前未分配的寬度,則先歸位x座標恢復預設值,從左邊開始重新分配空間
x = margin.left;
// y座標
y += context.getChildSize(maxHeightIndex).height + margin.top + margin.bottom;
// 找到座標後直接平移到對應位置畫出來
context.paintChild(i, transform: Matrix4.translationValues(x, y, 0.0));
// 下一次的x座標需要將它加上自己的寬度,和自己的左右邊距
x += context.getChildSize(i).width + margin.left + margin.right;
}
}
}
@override
bool shouldRepaint(FlowDelegate oldDelegate) {
return oldDelegate != this;
}
}
複製程式碼
Table
1、簡介
- Table控制元件具有控制寬度和位置的表格控制元件
2、建構函式
Table({
Key key,
this.children = const <TableRow>[],
this.columnWidths,
this.defaultColumnWidth = const FlexColumnWidth(1.0),
this.textDirection,
this.border,
this.defaultVerticalAlignment = TableCellVerticalAlignment.top,
this.textBaseline,
})
複製程式碼
- children:子控制元件集合
- columnWidths:表格的寬度
- defaultColumnWidth:預設表格的寬度
- top:頂部
- middle:垂直居中
- bottom:底部
- baseline:文字baseline對齊
- fill:充滿整個單元
- textDirection:文字的對齊方式
- border:表格的邊框
- defaultVerticalAlignment:預設的表格位置對齊方式
- textBaseline:文字baseline型別
- alphabetic:對齊字元底部的水平線
- ideographic:對齊表意字元的水平線
3、例子
將文字居底對齊的表格
Widget _buildColumn() {
return Table(
textDirection: TextDirection.ltr,
textBaseline: TextBaseline.alphabetic,
defaultColumnWidth: FixedColumnWidth(80.0),
defaultVerticalAlignment: TableCellVerticalAlignment.bottom,
border:
TableBorder.all(color: Colors.blueGrey, style: BorderStyle.solid),
columnWidths: {
0: FixedColumnWidth(50.0),
1: FixedColumnWidth(100.0),
2: FixedColumnWidth(100.0),
},
children: <TableRow>[
TableRow(children: [
Text("序號"),
Text("名字"),
Text("成績"),
]),
TableRow(children: [
Text("1"),
Text("張三"),
Text("80"),
]),
TableRow(children: [
Text("2"),
Text("李四"),
Text("88"),
]),
TableRow(children: [
Text("3"),
Text("王五"),
Text("92"),
])
]);
}
複製程式碼
Wrap
1、簡介
- Wrap控制元件相當於流式佈局,會自動換行,比Flex自定義的功能好用
2、建構函式
Wrap({
Key key,
this.direction = Axis.horizontal,
this.alignment = WrapAlignment.start,
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>[],
})
複製程式碼
- direction:主軸的方向
- Axis.horizontal:橫向排布
- Axis.vertical:豎向排布
- alignment:主軸方向上的對齊方式
- spacing:主軸方向上的間距
- runAlignment:橫向排布的話,表示一行的對齊方式,豎向排布的話,表示一列的對齊方式
- runSpacing:一行或者一列方向上的間距
- crossAxisAlignment:側軸方向的對齊方式
- textDirection:文字的對齊方式
- verticalDirection:子控制元件的排布方式
- down:從左上角到右下角進行佈局
- up:從右下角到左上角進行佈局
- children:子控制元件集合
3、例子
通過Wrap控制元件建立出豎向的流式佈局
Widget _buildColumn() {
return Wrap(
textDirection: TextDirection.ltr,
alignment: WrapAlignment.center,
verticalDirection: VerticalDirection.down,
crossAxisAlignment: WrapCrossAlignment.center,
direction: Axis.horizontal,
runAlignment: WrapAlignment.center,
runSpacing: 10.0,
spacing: 10.0,
children: <Widget>[
Chip(
label: Text("張三張三張三"),
),
Chip(
label: Text("李四李四李四"),
),
Chip(
label: Text("王五王五王五"),
),
Chip(
label: Text("趙六趙六趙六"),
),
Chip(
label: Text("錢七"),
),
Chip(
label: Text("孫八"),
),
],
);
}
複製程式碼
ListBody
1、簡介
- ListBody控制元件一般會配合ListView使用,屬於ListView的子節點
- ListBody控制元件的作用是按給定的軸方向,按照順序排列子節點
2、建構函式
ListBody({
Key key,
this.mainAxis = Axis.vertical,
this.reverse = false,
List<Widget> children = const <Widget>[],
})
複製程式碼
- mainAxis:主軸方向
- Axis.vertical:垂直方向
- Axis.horizontal:橫向方向
- reverse:是否控制元件翻轉過來
- children:子控制元件集合
3、例子
顯示3個不同顏色的容器,由於其父容器是Flex
,會導致ListBody
的側軸被拉昇到最大
Widget _buildColumn() {
return Flex(
direction: Axis.vertical,
children: <Widget>[
ListBody(
mainAxis: Axis.vertical,
reverse: false,
children: <Widget>[
Container(
height: 50,
width: 50,
color: Colors.blueAccent,
),
Container(
height: 50,
width: 50,
color: Colors.redAccent,
),
Container(
height: 50,
width: 50,
color: Colors.greenAccent,
)
],
),
],
);
}
複製程式碼
ListView
1、簡介
- ListView控制元件是個功能豐富的列表元件
2、建構函式
ListView({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
this.itemExtent,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
double cacheExtent,
List<Widget> children = const <Widget>[],
})
複製程式碼
- scrollDirection:滾動放向
- reverse:子控制元件是否翻轉
- controller:用來控制滾動位置及監聽滾動事件
- primary:當內容不足以滾動時,是否支援滾動
- physics:控制使用者滾動檢視的互動
- AlwaysScrollableScrollPhysics:列表總是可滾動的
- PageScrollPhysics:一頁一頁的列表滑動,一般用於PageView控制元件用的滑動效果,滑動到末尾會有比較大的彈起
- ClampingScrollPhysics:滾動時沒有回彈效果
- NeverScrollableScrollPhysics:就算內容超過列表範圍也不會滑動
- BouncingScrollPhysics:不論什麼平臺都會有回彈效果
- FixedExtentScrollPhysics:僅滾動到子項而不存在任何偏移,必須與使用FixedExtentScrollController的可滾動物件一起使用
- shrinkWrap:是否根據子widget的總長度來設定ListView的長度
- padding:父控制元件的內邊距
- itemExtent:指定子控制元件的固定高度
- addAutomaticKeepAlives:是否將子控制元件包裹在AutomaticKeepAlive控制元件內
- addRepaintBoundaries:是否將子控制元件包裹在 RepaintBoundary 控制元件內。用於避免列表滾動時的重繪
- cacheExtent:可見區域的前後會有一定高度的空間去快取子控制元件,當滑動時就可以迅速呈現
- children:子控制元件集合
3、例子
建立三個具有回彈功能的列表控制元件
Widget _buildColumn() {
return ListView(
physics: BouncingScrollPhysics(),
cacheExtent: 10.0,
primary: true,
padding: EdgeInsets.all(15.0),
reverse: false,
scrollDirection: Axis.vertical,
children: <Widget>[
Container(
height: 300,
width: 300,
color: Colors.blueAccent,
),
Container(
height: 300,
width: 300,
color: Colors.redAccent,
),
Container(
height: 300,
width: 300,
color: Colors.greenAccent,
)
],
);
}
複製程式碼
CustomMultiChildLayout
1、簡介
- CustomMultiChildLayout控制元件和CustomSingleChildLayout類似,區別於CustomMultiChildLayout可以控制多個控制元件
- CustomMultiChildLayout控制元件控制的子控制元件是通過Id進行區分和擺放
2、建構函式
CustomMultiChildLayout({
Key key,
@required this.delegate,
List<Widget> children = const <Widget>[],
})
複製程式碼
- delegate:控制子控制元件集合的代理類
- children:子控制元件集合
3、例子
首先建立控制元件的代理類,包括控制元件的大小和控制元件的位置,通過id獲取傳遞過來的子控制元件,將description
的控制元件放置在title
下方
class IdLayoutDelegate extends MultiChildLayoutDelegate {
IdLayoutDelegate();
@override
void performLayout(Size size) {
BoxConstraints constraints = BoxConstraints(maxWidth: size.width);
// 通過id獲取對應的控制元件大小
Size titleSize = layoutChild("title", constraints);
Size descriptionSize = layoutChild("description", constraints);
// 擺放id的控制元件位置
positionChild("title", Offset(0.0, 0.0));
positionChild("description", Offset(0.0, titleSize.height));
}
@override
bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) {
return oldDelegate != null;
}
}
複製程式碼
通過id將對應的控制元件擺佈在對應的位置
Widget _buildColumn() {
return CustomMultiChildLayout(
delegate: IdLayoutDelegate(),
children: <Widget>[
LayoutId(
id: "title",
child: Text("Hensen"),
),
LayoutId(
id: "description",
child: Text("Flutter工程師"),
)
],
);
}
複製程式碼
LayoutBuilder
1、簡介
- LayoutBuilder控制元件可以通過獲取父控制元件的約束條件,從而控制佈局的返回結果
2、建構函式
const LayoutBuilder({
Key key,
LayoutWidgetBuilder builder,
})
複製程式碼
- builder:子控制元件的構建者
3、例子
通過判斷父控制元件的尺寸大小,如果是大尺寸,就用大圖示,如果是小尺寸,就用小圖示
Widget _buildColumn() {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
if (constraints.maxWidth > 200.0) {
// 尺寸大的
return FlutterLogo(size: 200);
}
// 尺寸小的
return FlutterLogo(size: 50);
},
);
}
複製程式碼
作者
Hensen_ |