1、Row、Column
row 在水平方向上排列子widget的列表。
column 在垂直方向上排列子widget的列表。
a、Row、Column屬性
- MainAxisAlignment:主軸方向上的對齊方式,會對child的位置起作用,默認是start
center:將children放置在主軸的中心;
end:將children放置在主軸的末尾;
spaceAround:將主軸方向上的空白區域均分,使得children之間的空白區域相等,但是首尾child的空白區域爲1/2;
spaceBetween:將主軸方向上的空白區域均分,使得children之間的空白區域相等,首尾child都靠近首尾,沒有間隙;
spaceEvenly:將主軸方向上的空白區域均分,使得children之間的空白區域相等,包括首尾child;
start:將children放置在主軸的起點;
- MainAxisSize:在主軸方向佔有空間的值,默認是max。
max:根據傳入的佈局約束條件,最大化主軸方向的可用空間;
min:與max相反,是最小化主軸方向的可用空間;
- CrossAxisAlignment:children在交叉軸方向的對齊方式,
baseline:在交叉軸方向,使得children的baseline對齊;
center:children在交叉軸上居中展示;
end:children在交叉軸上末尾展示;
start:children在交叉軸上起點處展示;
stretch:讓children填滿交叉軸方向;
- TextDirection:阿拉伯語系的兼容設置,一般無需處理。
- VerticalDirection:定義了children擺放順序,默認是down。
down:從top到bottom進行佈局;
up:從bottom到top進行佈局。
- TextBaseline:使用的TextBaseline的方式
b、Row、Column案例
Widget row = new Row(
children: <Widget>[
Expanded(
child: Text(
'Deliver features faster',
textAlign: TextAlign.center,
)),
Expanded(
child: Text(
'Craft beautiful UIs ',
textAlign: TextAlign.center)),
Expanded(
child: FittedBox(
fit: BoxFit.contain,
child: const FlutterLogo(),
)),
],
);
Widget column = new Column(
children: <Widget>[
Text('Deliver features faster'),
Text('Craft beautiful UIs'),
Expanded(
child: FittedBox(
fit: BoxFit.contain, // otherwise the logo will be tiny
child: const FlutterLogo(),
),
),
],
);
3、Wrap
Wrap是一個可以使子控件自動換行的控件,默認的方向是水平的
a、Wrap屬性
- direction:主軸(mainAxis)的方向,默認爲水平。
- alignment:主軸方向上的對齊方式,默認爲start。
- spacing:主軸方向上的間距。
- runAlignment:run的對齊方式。run可以理解爲新的行或者列,如果是水平方向佈局的話,run可以理解爲新的一行。
- runSpacing:run的間距。
- crossAxisAlignment:交叉軸(crossAxis)方向上的對齊方式。
- textDirection:文本方向。
- verticalDirection:定義了children擺放順序,默認是down,見Flex相關屬性介紹。
4、Stack
跟Android中FrameLayout很像,都是可以疊加的現實View
a、Stack屬性
- alignment : 指的是子Widget的對其方式,
- fit :用來決定沒有Positioned方式時候子Widget的大小,
StackFit.loose 指的是子Widget 多大就多大,
StackFit.expand使子Widget 的大小和父組件一樣大
- overflow :指子Widget 超出Stack時候如何顯示,默認值是Overflow.clip,
Overflow.clip:子Widget超出Stack會被截斷,
Overflow.visible超出部分還會顯示的
- textDirection:排列方向
TextDirection.rtl: 從右到左
TextDirection.ltr: 從左到右
b、Stack案例
Widget stack = new Stack(
textDirection: TextDirection.rtl,
children: <Widget>[
Container(
width: 100,
height: 100,
color: Colors.red,
),
Container(
width: 90,
height: 90,
color: Colors.blue,
),
Container(
width: 80,
height: 80,
color: Colors.green,
)
],
);
c、Stack案例效果圖
5、IndexedStack
IndexedStack和Stack一樣,都是層佈局控件, 可以在一個控件上面放置另一個控件,但唯一不同的是IndexedStack在同一時刻只能顯示子控件中的一個控件,通過Index屬性來設置顯示的控件
a、IndexedStack屬性
擁有Stack屬性外,還有index屬性
- index:顯示第幾個圖案
6、Flow
一個實現流式佈局算法的widget,
Flow用起來遠比Wrap麻煩,但是它可以實現更加個性化的需求,我們可以通過delegate屬性自己設置子控件排列規則。
a、Flow屬性
-
Flowdelegate delegate :用於回調Flow大小,以及 計算childWidget的frame。
b、Flow案例
class TestFlowDelegate extends FlowDelegate {
EdgeInsets margin = EdgeInsets.zero;
TestFlowDelegate({this.margin});
@override
void paintChildren(FlowPaintingContext context) {
var x = margin.left;
var y = margin.top;
//計算每一個子widget的位置
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: new Matrix4.compose(Vector.Vector3(x,y,0.0), Vector.Quaternion(0.0,0.0,0.3,0.1), Vector.Vector3(1.0,1.0,1.0))
);
x = w + margin.left;
} else {
x = margin.left;
y += context.getChildSize(i).height + margin.top + margin.bottom;
//繪製子widget(有優化)
context.paintChild(i,
transform: Matrix4.translationValues(x, y, 0.0) //位移
);
x += context.getChildSize(i).width + margin.left + margin.right;
}
}
}
getSize(BoxConstraints constraints) {
//指定Flow的大小
return Size(double.infinity, double.infinity);
}
@override
bool shouldRepaint(FlowDelegate oldDelegate) {
return oldDelegate != this;
}
}
Flow flow = Flow(
delegate: TestFlowDelegate(margin: EdgeInsets.all(10.0)),
children: <Widget>[
new Container(width: 80.0, height: 80.0, color: Colors.red),
new Container(width: 80.0, height: 80.0, color: Colors.yellow),
new Container(width: 80.0, height: 80.0, color: Colors.green),
new Container(width: 80.0, height: 80.0, color: Colors.blue),
new Container(width: 80.0, height: 80.0, color: Colors.lightBlue),
new Container(width: 80.0, height: 80.0, color: Colors.black),
new Container(width: 80.0, height: 80.0, color: Colors.blueGrey),
new Container(width: 80.0, height: 80.0, color: Colors.brown),
new Container(width: 80.0, height: 80.0, color: Colors.black12),
],
);
c、IntrinsicHeight案例效果圖
6、Table
爲其子widget使用表格佈局算法的widget
a、Table屬性
- columnWidths:設置每一列的寬度
- defaultColumnWidth:默認的每一列寬度值,默認情況下均分
- textDirection:文字方向
- border:表格邊框
- defaultVerticalAlignment:默認垂直方向對齊方式:
- top:放置在頂部
- middle:垂直居中
- bottom:放置在底部
- baseline:文本baseline對齊
- fill:充滿整個cell
- textBaseline:defaultVerticalAlignment爲baseline的時候,會用到這個屬性
b、Table案例
Table table = new Table(
border: TableBorder.all(
width: 2.0, color: Colors.red, style: BorderStyle.solid),
children: <TableRow>[
new TableRow(
children: <TableCell>[
new TableCell(child: new Center(child: new Text("Hello 1"),)),
new TableCell(child: new Center(child: new Text("Hello 2"),)),
new TableCell(child: new Center(child: new Text("Hello 3"),)),
new TableCell(child: new Center(child: new Text("Hello 4"),))
],
),
new TableRow(
children: <TableCell>[
new TableCell(child: new Center(child: new Text("Hello 1"),)),
new TableCell(child: new Center(child: new Text("Hello 2"),)),
new TableCell(child: new Center(child: new Text("Hello 3"),)),
new TableCell(child: new Center(child: new Text("Hello 4"),))
],
),
new TableRow(
children: <TableCell>[
new TableCell(child: new Center(child: new Text("Hello 1"),)),
new TableCell(child: new Center(child: new Text("Hello 2"),)),
new TableCell(child: new Center(child: new Text("Hello 3"),)),
new TableCell(child: new Center(child: new Text("Hello 4"),))
],
),
new TableRow(
children: <TableCell>[
new TableCell(child: new Center(child: new Text("Hello 1"),)),
new TableCell(child: new Center(child: new Text("Hello 2"),)),
new TableCell(child: new Center(child: new Text("Hello 3"),)),
new TableCell(child: new Center(child: new Text("Hello 4"),))
],
),
],
);
c、Table案例效果圖
8、ListBody
ListBody的作用是按給定的軸方向,按照順序排列子節點。
a、ListBody屬性
- mainAxis:排列的主軸方向。
- reverse:是否反向。
b、ListBody案例
Widget flex = new Flex(
direction: Axis.horizontal,
children: <Widget>[
ListBody(
mainAxis: Axis.vertical,
reverse: false,
children: <Widget>[
Container(color: Colors.red, width: 50.0, height: 50.0,),
Container(color: Colors.yellow, width: 50.0, height: 50.0,),
Container(color: Colors.green, width: 50.0, height: 50.0,),
Container(color: Colors.blue, width: 50.0, height: 50.0,),
Container(color: Colors.black, width: 50.0, height: 50.0,),
],
),
],
);
c、ListBody案例效果圖
9、ListView
可滾動的列表控件。ListView是最常用的滾動widget,它在滾動方向上一個接一個地顯示它的孩子。在縱軸上,孩子們被要求填充ListView。
a、ListView構建方案
- 通過children屬性,即:用顯示的自列表來構造
List<Widget>,
此構造函數適合於具有少量子元素的列表視圖 ListView.builder
利用IndexedWidgetBuilder
來按需構造,這個構造函數適合於具有大量(或無限)子視圖的列表視圖,因爲構建器只對那些實際可見的子視圖調用。- 使用
ListView.separated
構造函數,採用兩個IndexedWidgetBuilder:itemBuilder
根據需要構建子項separatorBuilder
類似地構建出現在子項之間的分隔符子項。此構造函數適用於具有固定數量的子控件的列表視圖。 - 使用
ListView.custom
的SliverChildDelegate
構造,它提供了定製子模型的其他方面的能力。 例如,SliverChildDelegate
可以控制用於估計實際上不可見的孩子的大小的算法
b、ListView案例
//ListView.builder構建
ListView listView = new ListView.builder(
padding: EdgeInsets.all(10),
itemCount: 5,
itemExtent: 50.0,
itemBuilder: (BuildContext context,int index){
return new Text("Hello $index");
},
);
//ListView.separated構建
ListView listView = new ListView.separated(
itemCount: 5,
itemBuilder: (BuildContext context,int index){
return new Text("Hello $index");
},
separatorBuilder: (BuildContext context,int index){
return new Container(height: 10.0,color: Colors.red,);
},
);
//通過 ListView.custom構建
/**
* 繼承SliverChildBuilderDelegate 可以對列表的監聽
*/
class MySliverChildDelegate extends SliverChildBuilderDelegate{
/*這兩種效果等價*/
//MyDelegate(IndexedWidgetBuilder builder) : super(builder);
//MyDelegate(Widget Function(BuildContext, int) builder) : super(builder);
MySliverChildDelegate(IndexedWidgetBuilder builder,{
int childCount,
}) : super(builder,childCount:childCount);
////監聽 在可見的列表中 顯示的第一個位置和最後一個位置
@override
void didFinishLayout(int firstIndex, int lastIndex) {
// TODO: implement didFinishLayout
super.didFinishLayout(firstIndex, lastIndex);
}
//添加進來的實例與之前的實例是否相同 相同返回true 反之false
@override
bool shouldRebuild(SliverChildBuilderDelegate oldDelegate) {
// TODO: implement shouldRebuild
return super.shouldRebuild(oldDelegate);
}
}
ListView listView = new ListView.custom(
itemExtent: 40.0,
childrenDelegate: MySliverChildDelegate(
(BuildContext context, int i) {
return new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new Text(
"張三 name",
style: new TextStyle(fontSize: 18.0, color: Colors.red),
),
new Text(
"11 age}",
style: new TextStyle(fontSize: 18.0, color: Colors.green),
),
new Text(
"信息 content}",
style: new TextStyle(fontSize: 18.0, color: Colors.blue),
),
],
));
},
childCount: 10,
),
cacheExtent: 0.0,
);
c、ListView案例效果圖
通過ListView.builder實現效果
ListView.separated構建
ListView.custom