容器与布局
通常的,把只包含单个子Widget的Widget称为容器,把可以包含多个子Widget的Widget称为布局,实际上容器本身也是一种布局,因为布局本质上是指的对控件的位置的管理或控制。
万能容器
Container
它可以为 Widget 添加大小、背景等各种参数,其 child 属性用于设置它的子控件。由于它较为复杂,这里简述一下它的绘制顺序
- 首先会绘制
transform效果 - 接着绘制
decoration - 然后绘制
child - 最后绘制
foregroundDecoration
| 属性 | 类型 | 简述 |
|---|---|---|
| alignment | AlignmentGeometry | 容器内 child 的对齐方式 |
| padding | EdgeInsetsGeometry | 容器内边距 |
| color | Color | 容器的背景色 |
| decoration | Decoration | 容器的背景装饰 |
| foregroundDecoration | Decoration | 容器的前景装饰 |
| width | double | 容器的宽度 |
| height | double | 容器的高度 |
| constraints | BoxConstraints | 容器的大小限制 |
| margin | EdgeInsetsGeometry | 容器外边距 |
| transform | Matrix4 | 容器的变化 |
| child | Widget | 容器里显示的 Widget |
Container 本身是一个盒子模型
![图片[1]-Flutter 【容器布局组件(集合)】-IT网络技术分享](https://gitee.com/arcticfox1919/ImageHosting/raw/master/img/box.png)
Container(
width: 300.0,
height: 500.0,
margin: EdgeInsets.all(16.0),
padding: EdgeInsets.all(16.0),
alignment: Alignment.center,
decoration: BoxDecoration(
//背景填充颜色
color: Colors.amberAccent,
//背景边框
border: Border.all(
//边框颜色
color: Colors.black12,
//边框宽度
width: 5),
//边框圆角
borderRadius: BorderRadius.only(
topLeft: Radius.circular(5.0),
topRight: Radius.circular(10.0),
bottomLeft: Radius.circular(15.0),
bottomRight: Radius.circular(20.0)),
//渐变效果,会覆盖 color
gradient: LinearGradient(
colors: [Colors.redAccent, Colors.greenAccent, Colors.blueAccent],
),
//阴影效果
boxShadow: [BoxShadow(color: Colors.grey, blurRadius: 5.0)],
),
//前景装饰,绘制在 child 之上
foregroundDecoration: BoxDecoration(
image: DecorationImage(image: NetworkImage('https://gitee.com/arcticfox1919/ImageHosting/raw/master/img/emm.jpg'))
))
Container 简单总结
- 未设置约束和固定宽高时,若存在子控件,则原则上
Container和子控件一样大;不存在子控件,则原则上占满全屏。 - 若未设置约束和宽高,但设置了
alignment属性,且存在子控件,那么Container 原则上也会占满全屏 - 设置了固定宽高,则无论是否存在子控件,宽高都是固定的。
关于几个属性的类型:
alignment可使用三种类型的值
- Alignment
- FractionalOffset
- AlignmentDirectional
其中Alignment和FractionalOffset比较类似,而AlignmentDirectional主要用于国际化中左右顺序的支持。
margin与padding都使用相同类型的值,即EdgeInsets,该类型共用四中构造方法
- EdgeInsets.all()
- EdgeInsets.symmetric()
- EdgeInsets.fromLTRB()
- EdgeInsets.only()
decoration有四种类型,都是Decoration的子类,其中三种在开发中会用到
- BoxDecoration
- ShapeDecoration
- UnderlineTabIndicator
ShapeDecoration 通常是用于单独为四条边框绘制不同的效果,它的属性与BoxDecoration大致相同,其中shape属性是和BoxDecoration中不同的,类型为ShapeBorder,它的取值如下
- Border 绘制四边
- UnderlineInputBorder 绘制底边线
- RoundedRectangleBorder 绘制矩形边框
- CircleBorder 绘制圆形边框
- StadiumBorder 绘制竖向椭圆边框
- BeveledRectangleBorder 绘制八角边框
边距容器
Padding
主要用于设置控件之间的边距,用法参见Container
| 属性 | 类型 | 简述 |
|---|---|---|
| padding | EdgeInsetsGeometry | 容器内边距 |
| child | Widget | 容器里显示的 Widget |
基础布局
弹性布局
Flex
弹性布局,类似于 CSS 的 Flexbox。
| 属性 | 类型 | 简述 |
|---|---|---|
| direction | Axis | 主轴的方向 |
| mainAxisAlignment | MainAxisAlignment | 子Widget 在主轴的对齐方式 |
| mainAxisSize | MainAxisSize | 主轴应该占用多大的空间 |
| crossAxisAlignment | CrossAxisAlignment | 子Widget 在交叉轴的对齐方式 |
| textDirection | TextDirection | 子Widget 在主轴方向上的布局顺序 |
| verticalDirection | VerticalDirection | 子Widget 在交叉轴方向上的布局顺序 |
| textBaseline | TextBaseline | 子Widget 时使用哪个基线 |
| children | List< Widget> | Flex布局里排列的子控件 |
direction 的取值:主轴的方向
| Axis 值 | 简述 |
|---|---|
| Axis.horizontal | 主轴为水平方向,子Widget 就会沿水平方向排列,则交叉轴为垂直方向。 |
| Axis.vertical | 主轴为垂直方向,子Widget 就会沿垂直方向排列,则交叉轴为水平方向。 |
mainAxisAlignment 的取值:子控件在主轴的对齐方式
| MainAxisAlignment 值 | 简述 |
|---|---|
| MainAxisAlignment.start | 沿着主轴的起点对齐 textDirection 必须有值,以确定是从左边开始的还是从右边开始的 |
| MainAxisAlignment.end | 沿着主轴的终点对齐 textDirection 必须有值,以确定是在左边结束的还是在右边结束的 |
| MainAxisAlignment.center | 在主轴上居中对齐 |
| MainAxisAlignment.spaceBetween | 在主轴上,两端对齐,子控件之间的间隔都相等 |
| MainAxisAlignment.spaceAround | 在主轴上,将多余的控件均匀分布给 子控件之间,而且第一个 子Widget 和 最后一个子Widget 距边框的距离是 两个 子Widget 距离的一半 |
| MainAxisAlignment.spaceEvenly | 在主轴上,将多余的控件均匀分布给子控件之间,而且第一个 子Widget 和 最后一个子Widget 距边框的距离和 子控件之间的距离一样 |
其中最后三个属性不太好理解,这里给出图示:
MainAxisAlignment.spaceBetween
两端顶格,中间均分
![图片[2]-Flutter 【容器布局组件(集合)】-IT网络技术分享](https://gitee.com/arcticfox1919/ImageHosting/raw/master/img/Screenshot_1587064481.png)
MainAxisAlignment.spaceAround
该效果我称为拉手布局,相当于小朋友伸开手,且相互间手拉手。
![图片[3]-Flutter 【容器布局组件(集合)】-IT网络技术分享](https://gitee.com/arcticfox1919/ImageHosting/raw/master/img/Screenshot_1587064048.png)
MainAxisAlignment.spaceEvenly
均分间距
![图片[4]-Flutter 【容器布局组件(集合)】-IT网络技术分享](https://gitee.com/arcticfox1919/ImageHosting/raw/master/img/Screenshot_1587064808.png)
mainAxisSize 的取值 : 表示主轴应该占用多大的空间
| MainAxisSize 值 | 简述 |
|---|---|
| MainAxisSize.min | 主轴的大小是能显示完 子Widget 的最小大小,主轴的大小就是 子Widget 的大小 |
| MainAxisSize.max | 主轴能显示的最大的大小,根据约束来判断 |
crossAxisAlignment 的取值:子控件在交叉轴的对齐方式
| CrossAxisAlignment 值 | 简述 |
|---|---|
| CrossAxisAlignment.start | 沿着交叉轴的起点对齐 verticalDirection 必须有值,以确定是从左边开始的还是从右边开始的 |
| CrossAxisAlignment.end | 沿着主轴的终点对齐 verticalDirection 必须有值,以确定是在左边结束的还是在右边结束的 |
| CrossAxisAlignment.center | 在交叉轴上居中对齐 |
| CrossAxisAlignment.stretch | 要求 子Widget 在交叉轴上填满 |
| CrossAxisAlignment.baseline | 要求 子Widget 的基线在交叉轴上对齐 |
textDirection 的取值:子控件在主轴方向上的布局顺序
| TextDirection 值 | 简述 |
|---|---|
| TextDirection.rtl | 表示从右到左 |
| TextDirection.ltr | 表示从左到右 |
verticalDirection 的取值 :子控件在交叉轴方向上的布局顺序
| VerticalDirection 值 | 简述 |
|---|---|
| VerticalDirection.up | 表示从下到上 |
| VerticalDirection.down | 表示从上到下 |
线性布局
Row
水平方向的线性布局
| 属性 | 类型 | 简述 |
|---|---|---|
| mainAxisAlignment | MainAxisAlignment | 子Widget 在主轴的对齐方式 |
| mainAxisSize | MainAxisSize | 表示主轴应该占用多大的空间 |
| crossAxisAlignment | CrossAxisAlignment | 子Widget 在交叉轴的对齐方式 |
| textDirection | TextDirection | 子Widget 在主轴方向上的布局顺序 |
| verticalDirection | VerticalDirection | 子Widget 在交叉轴方向上的布局顺序 |
| textBaseline | TextBaseline | 设置 子Widget 基线 |
| children | List< Widget> | 用于排列的子控件列表 |
Column
垂直方向的线性布局,其属性可直接参照Row
流式布局
Wrap
| 属性 | 类型 | 简述 |
|---|---|---|
| direction | Axis | 主轴的方向。默认是 Axis.horizontal |
| alignment | WrapAlignment | 子Widget 在主轴上的对齐方式,默认值为WrapAlignment.start |
| runAlignment | WrapAlignment | 纵轴对齐方式,默认值为WrapAlignment.start |
| runSpacing | double | 纵轴间距,默认是0.0 |
| crossAxisAlignment | WrapCrossAlignment | 交叉轴上的对齐方式 |
| textDirection | TextDirection | 子Widget 在主轴方向上的排列顺序 |
| verticalDirection | VerticalDirection | 子Widget 在交叉轴方向上的排列顺序 |
| children | List< Widget> | 子控件列表 |
层叠布局
Stack
| 属性 | 类型 | 简述 |
|---|---|---|
| alignment | AlignmentDirectional | 决定子Widget如何对齐 ,默认值为 AlignmentDirectional.topStart |
| textDirection | TextDirection | 用于确定 alignment的对齐方向 |
| fit | StackFit | 决定非positioned子Widget 如何去适应Stack的大小 |
| overflow | Overflow | 如何显示超出 Stack空间的 子widget |
| children | List< Widget> | 排列的子控件 |
在Stack布局中,通常会与另外两个控件配合使用,它们是Align和Positioned,前者用于相对定位,后者用于绝对定位。
Align比较简单,这里列一下Positioned的属性
| 属性 | 类型 | 简述 |
|---|---|---|
| left | double | 离 Stack 左边的距离 |
| top | double | 离 Stack 上边的距离 |
| right | double | 离 Stack 右边的距离 |
| bottom | double | 离 Stack 底边的距离 |
| width | double | 设定子控件的宽度 |
| height | double | 设定子控件的高度 |
辅助布局
Center
水平垂直居中布局。类似Container设置alignment
SizedBox
固定宽高布局,类似Container设置了宽高
AspectRatio
宽高比布局。
FractionallySizedBox
百分比布局。
Card
卡片布局。
高级布局
列表 ListView
它是一种可滚动的列表,共四种构造方法。其中最常用的是ListView.builder构造方法,因为它适用于大量的列表项的情形,甚至可以是无限数量的项。
ListView()ListView.builder()ListView.separated()ListView custom()
网格 GridView
用于创建二维网格列表。
GridView()默认构造GridView.count用于快速的创建固定横轴数量的网格GridView.extent用于创建交叉轴子最大可容纳的网格GridView.builder同ListView的builderGridView.custom用于构建自定义子Widget
GridView.count 是在交叉轴上创建固定个数的网格,crossAxisCount为必须的属性,表示交叉轴网格的个数,而GridView.extent是在交叉轴上创建最大可容纳的网格,maxCrossAxisExtent是必须的属性,表示交叉轴上网格的最大的宽度。
表格 Table/TableRow
表格布局和线性布局比较相似,只是使用起来更简洁一些。
| 属性 | 类型 | 简述 |
|---|---|---|
| columnWidths | Map<int, TableColumnWidth> | 设置每一列的宽度 |
| defaultColumnWidth | TableColumnWidth | 默认的每一列宽度值,默认情况下均分 |
| textDirection | TextDirection | 文字方向 |
| border | TableBorder | 表格边框 |
| defaultVerticalAlignment | TableCellVerticalAlignment | 每一个cell的垂直方向的alignment |
| children | List<TableRow> | 子控件列表 |
示例
Container(
child: Table(
columnWidths: const {
//列宽
0: FixedColumnWidth(100.0),
1: FixedColumnWidth(200.0),
2: FixedColumnWidth(50.0),
},
border: TableBorder.all(
color: Colors.green,
width: 2.0,
style: BorderStyle.solid,
),
children: [
TableRow(
decoration: BoxDecoration(
color: Colors.grey,
),
children: [
SizedBox(
height: 30.0,
child: Text('姓名'),
),
Text('性别'),
Text('年龄'),
]
),
TableRow(
children: [
Text('张三'),
Text('男'),
Text('20'),
]
),
TableRow(
children: [
Text('李四'),
Text('女'),
Text('28'),
]
),
],
),
);
栈索引
IndexedStack 继承自Stack,用于显示第index个child,而其他child则是不可见的。所以IndexedStack的尺寸永远是跟最大的子控件尺寸一致。与Stack相比,只是多了index的设置。
class _HomePageState extends State<HomePage> {
int _pageIndex = 0;
@override
Widget build(BuildContext context) {
print("_HomePageState build ...");
const bgColor = const [
Colors.red,
Colors.green,
Colors.blue,
Colors.yellow
];
return Scaffold(
appBar: AppBar(
title: Text("Flutter Widget"),
),
body: Container(
child: Column(
children: <Widget>[
Expanded(
child: IndexedStack(
index: _pageIndex,
children: <Widget>[
Container(
color: Colors.red,
),
Container(
color: Colors.green,
),
Container(
color: Colors.blue,
),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(child: Text("1"),onPressed: ()=>onClick(0),),
FlatButton(child: Text("2"),onPressed: ()=>onClick(1)),
FlatButton(child: Text("3"),onPressed: ()=>onClick(2)),
],
)
],
),
),
);
}
void onClick(int index){
setState(() {
_pageIndex = index;
});
}
}






暂无评论内容