1.容器组件
1)Container
常用属性:
- key:Container唯一标识符,用于查找更新。
- alignment:控制child的对齐方式,如果container或者container父节点尺寸大于child的尺寸,这个属性设置会起作用,有很多种对齐方式。
- padding:decoration内部的空白区域,如果有child的话,child位于padding内部。padding与margin的不同之处在于,padding是包含在content内,而margin则是外部边界,设置点击事件的话,padding区域会响应,而margin区域不会响应。
- color:用来设置container背景色,如果foregroundDecoration设置的话,可能会遮盖color效果。
- decoration:绘制在child后面的装饰,设置了decoration的话,就不能设置color属性,否则会报错。可以设置背景图片、边框、阴影等跟iOS中CALayer差不多。
- foregroundDecoration:绘制在child前面的装饰。
- width:container的宽度,设置为double.infinity可以强制在宽度上撑满,不设置,则根据child和父节点两者一起布局。
- height:container的高度,设置为double.infinity可以强制在高度上撑满。
- constraints:添加到child上额外的约束条件。
- margin:围绕在decoration和child之外的空白区域,不属于内容区域。
- transform:设置container的变换矩阵,类型为Matrix4。
- child:container中的内容widget。
2)Padding
作为一个基础的控件,功能非常单一,给子节点设置padding属性。
Padding的布局分为两种情况:
- 当child为空的时候,会产生一个宽为left+right,高为top+bottom的区域;
- 当child不为空的时候,Padding会将布局约束传递给child,根据设置的padding属性,缩小child的布局尺寸。然后Padding将自己调整到child设置了padding属性的尺寸,在child周围创建空白区域。
源码:
const Padding({
Key key,
@required this.padding, //设置内边距
Widget child, // 子控件
})
2)Align
Align的布局行为分为两种情况:
- 当widthFactor和heightFactor为null的时候,当其有限制条件的时候,Align会根据限制条件尽量的扩展自己的尺寸,当没有限制条件的时候,会调整到child的尺寸;
- 当widthFactor或者heightFactor不为null的时候,Aligin会根据factor属性,扩展自己的尺寸,例如设置widthFactor为2.0的时候,那么,Align的宽度将会是child的两倍。
源码:
const Align({
Key key,
this.alignment: Alignment.center,
this.widthFactor,// 宽度因子,如果设置的话,Align的宽度就是child的宽度乘以这个值,不能为负数。不设置的话则尽量扩展。
this.heightFactor,// 高度因子,如果设置的话,Align的高度就是child的高度乘以这个值,不能为负数。不设置的话则尽量扩展。
Widget child
})
3)Center
Center继承自Align,,只不过是将alignment设置为Alignment.center,其他属性例如widthFactor、heightFactor,布局行为,都与Align完全一样。
源码:
class Center extends Align {
/// Creates a widget that centers its child.
const Center({ Key key, double widthFactor, double heightFactor, Widget child })
: super(key: key, widthFactor: widthFactor, heightFactor: heightFactor, child: child);
}
4)FittedBox
布局行为分两种情况:
- 如果外部有约束的话,按照外部约束调整自身尺寸,然后缩放调整child,按照指定的条件进行布局;
- 如果没有外部约束条件,则跟child尺寸一致,指定的缩放以及位置属性将不起作用。
FittedBox会在自己的尺寸范围内缩放并且调整child位置,使得child适合其尺寸。
源码:
const FittedBox({
Key key,
this.fit = BoxFit.contain,
this.alignment = Alignment.center,
this.clipBehavior = Clip.hardEdge,
Widget child,
})
示例:
Container(
color: Colors.amberAccent,
width: 300.0,
height: 300.0,
child: new FittedBox(
fit: BoxFit.contain,
alignment: Alignment.topLeft,
child: new Container(
color: Colors.red,
child: new Text("FittedBox"),
),
),
)
5)SizedBox
SizedBox布局行为:
- child不为null时,如果设置了宽高,则会强制把child尺寸调到此宽高;如果没有设置宽高,则会根据child尺寸进行调整;
- child为null时,如果设置了宽高,则自身尺寸调整到此宽高值,如果没设置,则尺寸为0;
源码:
const SizedBox({
Key key,
this.width,
this.height,
Widget child })
示例:
ontainer(
color: Colors.green,
padding: const EdgeInsets.all(5.0),
child: SizedBox(
width: 200.0,
height: 200.0,
child: Container(
color: Colors.red,
width: 100.0,
height: 300.0,
),
),
)
2.布局组件
1)Flex
弹性布局允许子组件按照一定比例来分配父容器空间。Flex组件可以沿着水平或垂直方向排列子组件,如果你知道主轴方向,使用Row或Column会方便一些,因为Row和Column都继承自Flex,参数基本相同,所以能使用Flex的地方基本上都可以使用Row或Column。Flex本身功能是很强大的,它也可以和Expanded组件配合实现弹性布局。
Flex({
Key key,
@required this.direction,
this.mainAxisAlignment = MainAxisAlignment.start,
this.mainAxisSize = MainAxisSize.max,
this.crossAxisAlignment = CrossAxisAlignment.center,
this.textDirection,
this.verticalDirection = VerticalDirection.down,
this.textBaseline,
this.clipBehavior = Clip.hardEdge,
List<Widget> children = const <Widget>[],
})
- direction:主轴方向。
- MainAxisAlignment:主轴方向上的对齐方式,会对child的位置起作用,默认是start。
MainAxisAlignment枚举值:
center:将children放置在主轴的中心;
end:将children放置在主轴的末尾;
spaceAround:将主轴方向上的空白区域均分,使得children之间的空白区域相等,但是首尾child的空白区域为1/2;
spaceBetween:将主轴方向上的空白区域均分,使得children之间的空白区域相等,首尾child都靠近首尾,没有间隙;
spaceEvenly:将主轴方向上的空白区域均分,使得children之间的空白区域相等,包括首尾child;
start:将children放置在主轴的起点;
- MainAxisSize:在主轴方向占有空间的值,默认是max。根据传入的布局约束条件,最大化主轴方向的可用空间;min,与max相反,是最小化主轴方向的可用空间。
- CrossAxisAlignment:children在交叉轴方向的对齐方式,与MainAxisAlignment略有不同。
CrossAxisAlignment枚举值有如下几种:
baseline:在交叉轴方向,使得children的baseline对齐;
center:children在交叉轴上居中展示;
end:children在交叉轴上末尾展示;
start:children在交叉轴上起点处展示;
stretch:让children填满交叉轴方向;
- TextDirection:阿拉伯语系的兼容设置,一般无需处理。
- VerticalDirection:定义了children摆放顺序,默认是down,从top到bottom进行布局。up,从bottom到top进行布局。
- TextBaseline:字符对其方式。
Expanded组件可以使Row、Column、Fiex等子组件在其主轴上方向展开并填充可用的空间。
源码:
const Expanded({
Key key,
int flex = 1,flex // 分配空间的弹性系数,Row,Column或Flex的每个Expanded的flex构成空间分配的比例,默认int flex = 1
@required Widget child,
})
示例:
Flex(
direction: Axis.horizontal,
children: <Widget>[
Expanded(
flex: 1,
child: Container(
height: 30.0,
color: Colors.red,
),
),
Expanded(
flex: 2,
child: Container(
height: 30.0,
color: Colors.green,
),
),
],
),
2)Row、Column
将children排列成一行或者一列,自身不带滚动属性,如果超出了一行,在debug下面则会显示溢出的提示。
源码:
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>[],
})
Flex的构造函数就比Row和Column的多了一个参数。Row跟Column的区别,正是这个direction参数的不同。当为Axis.horizontal的时候,则是Row,当为Axis.vertical的时候,则是Column。
示例:
Row(
children: <Widget>[
Expanded(
child: Container(
color: Colors.red,
padding: EdgeInsets.all(5.0),
),
flex: 1,
),
Expanded(
child: Container(
color: Colors.yellow,
padding: EdgeInsets.all(5.0),
),
flex: 2,
),
Expanded(
child: Container(
color: Colors.blue,
padding: EdgeInsets.all(5.0),
),
flex: 1,
),
],
)
3)Stack
Stack可以类比web中的absolute,绝对布局。对于绘制child的顺序,则是第一个child被绘制在最底端,后面的依次在前一个child的上面,类似于web中的z-index。如果想调整显示的顺序,则可以通过摆放child的顺序来进行。
源码:
Stack({
Key key,
this.alignment = AlignmentDirectional.topStart,
this.textDirection,
this.fit = StackFit.loose,
this.overflow = Overflow.clip,
List<Widget> children = const <Widget>[],
})
- alignment : 指的是子Widget的对其方式,默认情况是以左上角为开始点,这个属性是最难理解的,它区分为使用了Positioned和未使用Positioned定义两种情况。
对于positioned的子节点,它们的位置会根据所设置的top、bottom、right以及left属性来确定,这几个值都是相对于Stack的左上角。
对于non-positioned的子节点,它们会根据Stack的aligment来设置位置。
- fit :用来决定没有Positioned方式时候子Widget的大小,StackFit.loose 指的是子Widget 多大就多大,StackFit.expand使子Widget的大小和父组件一样大。
- overflow :指子Widget超出Stack时候如何显示,默认值是Overflow.clip,子Widget超出Stack会被截断,Overflow.visible超出部分还会显示的。
Positioned:
源码:
Positioned({
Key key,
this.left,
this.top,
this.right,
this.bottom,
this.width,
this.height,
@required Widget child,
})
left、top 、right、bottom分别代表离Stack左、上、右、底四边的距离。
示例:
Stack(
children: <Widget>[
Positioned(
top: 100.0,
child: Container(
color: Colors.blue,
child: Text("第一个组件"),
),
),
Positioned(
top: 200,
right: 100,
child: Container(
color: Colors.yellow,
child: Text("第二个组件"),
),
),
Positioned(
left: 100.0,
child: Container(
color: Colors.red,
child: Text("第三个组件"),
),
),
],
),