1.Row
线性布局,将children排成一行,主轴为水平方向,交叉轴为垂直方向。
- textDirection:表示水平方向子widget的布局顺序是从左往右还是从右往左。
- mainAxisSize:主轴方向的占用空间。默认是MainAxisSize.max,表示尽可能多的占用水平方向的空间,此时无论子widgets实际占用多少水平空间,Row的宽度始终等于水平方向的最大宽度;而MainAxisSize.min表示尽可能少的占用水平空间,当子widgets没有占满水平剩余空间,则Row的实际宽度等于所有子widgets占用的的水平空间;
- mainAxisAlignment:主轴对齐方式,如果mainAxisSize值为MainAxisSize.min ,则此属性无意义,因为子widgets的宽度等于Row的宽度。只有当mainAxisSize的值为MainAxisSize.max时,此属性才有意义。textDirection是mainAxisAlignment的参考系,textDirection取值为TextDirection.ltr时,则MainAxisAlignment.start表示左对齐,textDirection取值为TextDirection.rtl时表示从右对齐。
- crossAxisAlignment:交叉轴对齐方式,Row的高度等于子Widgets中最高的子元素高度。crossAxisAlignment的参考系是verticalDirection,即verticalDirection值为VerticalDirection.down时crossAxisAlignment.start指顶部对齐,verticalDirection值为VerticalDirection.up时,crossAxisAlignment.start指底部对齐;而crossAxisAlignment.end和crossAxisAlignment.start正好相反;
- children :子widget数组
2.Column
Column可以在垂直方向排列其子widget。参数和Row一样,不同的是布局方向为垂直,主轴纵轴正好相反
如果Row里面嵌套Row,或者Column里面再嵌套Column,那么只有对最外面的Row或Column会占用尽可能大的空间,里面Row或Column所占用的空间为实际大小
3.Stack
可以允许其子widget简单的堆叠在一起,相当于Android中的FrameLayout,
- alignment:此参数决定如何去对齐没有定位(没有使用Positioned)或部分定位的子widget。所谓部分定位,在这里特指没有在某一个轴上定位:left、right为横轴,top、bottom为纵轴,只要包含某个轴上的一个定位属性就算在该轴上有定位。
- textDirection:决定alignment对齐的参考系即:textDirection的值为TextDirection.ltr,则alignment的start代表左,end代表右;textDirection的值为TextDirection.rtl,则alignment的start代表右,end代表左。
- fit:此参数用于决定没有定位的子widget如何去适应Stack的大小。StackFit.loose表示使用子widget的大小,StackFit.expand表示扩伸到Stack的大小,passthrough不改变子widget的约束条件。
- overflow:此属性决定如何显示超出Stack显示空间的子widget,值为Overflow.clip时,超出部分会被剪裁(隐藏),值为Overflow.visible 时则不会。
Positioned
const Positioned({
Key key,
this.left,
this.top,
this.right,
this.bottom,
this.width,
this.height,
@required Widget child,
})
left、top 、right、 bottom分别代表离Stack左、上、右、底四边的距离。width和height用于指定定位元素的宽度和高度,注意,此处的width、height 和其它地方的意义稍微有点区别,此处用于配合left、top 、right、 bottom来定位widget,举个例子,在水平方向时,你只能指定left、right、width三个属性中的两个,如指定left和width后,right会自动算出(left+width),如果同时指定三个属性则会报错,垂直方向同理。
4.IndexedStack
IndexedStack继承自Stack,它的作用是显示第index个child,其他child都是不可见的。所以IndexedStack的尺寸永远是跟最大的子节点尺寸一致。
5.Wrap
子Widget超出屏幕范围会自动换行,Wrap的很多属性在Row(包括Flex和Column)中也有,如direction、crossAxisAlignment、textDirection、verticalDirection等
- direction:主轴(mainAxis)的方向,默认为水平。
- alignment:主轴方向上的对齐方式,默认为start。
- spacing:主轴方向子widget的间距
- runSpacing:纵轴方向的间距
- runAlignment:纵轴方向的对齐方式
6.Flow
一个实现流式布局算法的widget,使用比较复杂,一般多实用Wrap
7.Table
为其子widget使用表格布局算法的widget,
Table({
Key key,
this.children = const [],
this.columnWidths,
this.defaultColumnWidth = const FlexColumnWidth(1.0),
this.textDirection,
this.border,
this.defaultVerticalAlignment = TableCellVerticalAlignment.top,
this.textBaseline,
})
- columnWidths:设置每一列的宽度。
- defaultColumnWidth:默认的每一列宽度值,默认情况下均分。
- textDirection:文字方向
- border:表格边框。
- defaultVerticalAlignment:每一个cell的垂直方向的alignment。
总共包含5种:
top:被放置在的顶部;
middle:垂直居中;
bottom:放置在底部;
baseline:文本baseline对齐;
fill:充满整个cell。 - textBaseline:defaultVerticalAlignment为baseline的时候,会用到这个属性。
8.ListView
ListView是最常用的可滚动widget,它可以沿一个方向线性排布所有子widget。
- itemExtent:该参数如果不为null,则会强制children的"长度"为itemExtent的值;这里的"长度"是指滚动方向上子widget的长度,即如果滚动方向是垂直方向,则itemExtent代表子widget的高度,如果滚动方向为水平方向,则itemExtent代表子widget的长度。在ListView中,指定itemExtent比让子widget自己决定自身长度会更高效,这是因为指定itemExtent后,滚动系统可以提前知道列表的长度,而不是总是动态去计算,尤其是在滚动位置频繁变化时(滚动系统需要频繁去计算列表高度)。
- shrinkWrap:该属性表示是否根据子widget的总长度来设置ListView的长度,默认值为false 。默认情况下,ListView的会在滚动方向尽可能多的占用空间。当ListView在一个无边界(滚动方向上)的容器中时,shrinkWrap必须为true。
- addAutomaticKeepAlives:该属性表示是否将列表项(子widget)包裹在AutomaticKeepAlive widget中;典型地,在一个懒加载列表中,如果将列表项包裹在AutomaticKeepAlive中,在该列表项滑出视口时该列表项不会被GC,它会使用KeepAliveNotification来保存其状态。如果列表项自己维护其KeepAlive状态,那么此参数必须置为false。
- addRepaintBoundaries:该属性表示是否将列表项(子widget)包裹在RepaintBoundary中。当可滚动widget滚动时,将列表项包裹在RepaintBoundary中可以避免列表项重绘,但是当列表项重绘的开销非常小(如一个颜色块,或者一个较短的文本)时,不添加RepaintBoundary反而会更高效。和addAutomaticKeepAlive一样,如果列表项自己维护其KeepAlive状态,那么此参数必须置为false。
默认构造函数
ListView(
shrinkWrap: true,
padding: EdgeInsets.all(20.0),
children: [
Text('I\'m dedicating every day to you'),
Text('Domestic life was never quite my style'),
Text('When you smile, you knock me out, I fall apart'),
Text('And I thought I was so smart'),
],
)
ListView.builder
ListView.builder(
itemCount: 1000,
itemBuilder: (context, index) {
return ListTile(
title: Text("$index"),
);
},
)
ListView.separated
class ListView3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
//下划线widget预定义以供复用。
Widget divider1=Divider(color: Colors.blue,);
Widget divider2=Divider(color: Colors.green);
return ListView.separated(
itemCount: 100,
//列表项构造器
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text("$index"));
},
//分割器构造器
separatorBuilder: (BuildContext context, int index) {
return index%2==0?divider1:divider2;
},
);
}
}
9.GridView
一个滚动的多列列表
默认构造函数
GridView({
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
@required SliverGridDelegate gridDelegate, //控制子widget layout的委托
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
double cacheExtent,
List children = const [],
})
- scrollDirection:滚动的方向,有垂直和水平两种,默认为垂直方向(Axis.vertical)。
- reverse:默认是从上或者左向下或者右滚动的,这个属性控制是否反向,默认值为false,不反向滚动。
- controller:控制child滚动时候的位置。
- primary:是否是与父节点的PrimaryScrollController所关联的主滚动视图。
- physics:滚动的视图如何响应用户的输入。
- shrinkWrap:滚动方向的滚动视图内容是否应该由正在查看的内容所决定。
- padding:四周的空白区域。
- cacheExtent:缓存区域。
- gridDelegate:控制GridView中子节点布局的delegate。
gridDelegate参数,类型是SliverGridDelegate,它的作用是控制GridView子widget如何排列(layout),SliverGridDelegate是一个抽象类,定义了GridView Layout相关接口,子类需要通过实现它们来实现具体的布局算法,Flutter中提供了两个SliverGridDelegate的子类SliverGridDelegateWithFixedCrossAxisCount和SliverGridDelegateWithMaxCrossAxisExtent
SliverGridDelegateWithFixedCrossAxisCount
该类通过确定横轴子widget的数量和宽高比从而确定了子widget的最大限时空间
SliverGridDelegateWithFixedCrossAxisCount({
@required double crossAxisCount,
double mainAxisSpacing = 0.0,
double crossAxisSpacing = 0.0,
double childAspectRatio = 1.0,
})
- crossAxisCount:横轴子元素的数量。此属性值确定后子元素在横轴的长度就确定了,即ViewPort横轴长度/crossAxisCount。
- mainAxisSpacing:主轴方向的间距。
- crossAxisSpacing:横轴方向子元素的间距。
- childAspectRatio:子元素在横轴长度和主轴长度的比例。由于crossAxisCount指定后子元素横轴长度就确定了,然后通过此参数值就可以确定子元素在主轴的长度。
SliverGridDelegateWithMaxCrossAxisExtent
该类通过确定子widget在交叉轴的最大长度和宽高比从而确定了子widget的最大限时空间
SliverGridDelegateWithMaxCrossAxisExtent({
double maxCrossAxisExtent,
double mainAxisSpacing = 0.0,
double crossAxisSpacing = 0.0,
double childAspectRatio = 1.0,
})
- maxCrossAxisExtent:子widget在交叉轴的最大长度,因为每个子元素的长度仍然是等分的,所以会按照设置的长度计算出能展示的数量然后算出长度的最大值,当maxCrossAxisExtent的值在区间(450/4,450/3]内的话,子元素最终实际长度都为150
GridView.count
GridView.count构造函数内部使用了SliverGridDelegateWithFixedCrossAxisCount,我们通过它可以快速的创建横轴固定数量子元素的GridView
GridView.count(
crossAxisCount: 3,
childAspectRatio: 1.0,
children: [
Icon(Icons.ac_unit),
Icon(Icons.airport_shuttle),
Icon(Icons.all_inclusive),
Icon(Icons.beach_access),
Icon(Icons.cake),
Icon(Icons.free_breakfast),
],
);
GridView.extent
GridView.extent构造函数内部使用了SliverGridDelegateWithMaxCrossAxisExtent,我们通过它可以快速的创建纵轴子元素为固定最大长度的的GridView
GridView.extent(
maxCrossAxisExtent: 120.0,
childAspectRatio: 2.0,
children: [
Icon(Icons.ac_unit),
Icon(Icons.airport_shuttle),
Icon(Icons.all_inclusive),
Icon(Icons.beach_access),
Icon(Icons.cake),
Icon(Icons.free_breakfast),
],
);
GridView.builder
上面我们介绍的GridView都需要一个Widget数组作为其子元素,这些方式都会提前将所有子widget都构建好,所以只适用于子Widget数量比较少时,当子widget比较多时,我们可以通过GridView.builder来动态创建子Widget。
GridView.builder 必须指定的参数有两个:
GridView.builder(
...
@required SliverGridDelegate gridDelegate,
@required IndexedWidgetBuilder itemBuilder,
)