本篇文章主要讲解一下Flutter中的布局知识。
- Alignment
- Row
- Column
- Stack
- AspectRatio
1. Alignment
把Alignment单独拿出来是因为在Container的布局有点繁琐,先从一个简单的代码看一下Container里面的alignment
:
class BoxRowDemo extends StatelessWidget {
final TextStyle _textStyle = TextStyle(
color: Colors.white,
fontSize: 36.0,
);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.deepPurple,
// alignment: Alignment(1.0,0.0),
child: Text('一个阿狸',style: _textStyle,),
);
}
}
看到运行的效果图,想必已经大致知道了设个Alignment的的作用,Container的布局行为的先后顺序是这样的:
- 采用alignment
- 以child改变大小
- 用了width、height、constraints
- 适应父Widget
- 尽可能小
源码中可以看到Alignment的一些默认值:
/// The top left corner.
static const Alignment topLeft = Alignment(-1.0, -1.0);
/// The center point along the top edge.
static const Alignment topCenter = Alignment(0.0, -1.0);
/// The top right corner.
static const Alignment topRight = Alignment(1.0, -1.0);
/// The center point along the left edge.
static const Alignment centerLeft = Alignment(-1.0, 0.0);
/// The center point, both horizontally and vertically.
static const Alignment center = Alignment(0.0, 0.0);
/// The center point along the right edge.
static const Alignment centerRight = Alignment(1.0, 0.0);
/// The bottom left corner.
static const Alignment bottomLeft = Alignment(-1.0, 1.0);
/// The center point along the bottom edge.
static const Alignment bottomCenter = Alignment(0.0, 1.0);
2. Row
来直接看一个Row的简单代码,容器里放置3个不同大小的小容器:
class BoxRowDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.deepPurple,
alignment: Alignment(0.0,0.0),
child: Row(
children: <Widget>[
Container(
color: Colors.red,
width: 80,
height: 80,
),
Container(
color: Colors.green,
width: 60,
height: 60,
),
Container(
color: Colors.blue,
width: 100,
height: 100,
)
],
),
);
}
}
运行效果就跟我们预想的一样,是横向排列的。在这里有一个mainAxisAlignment
和crossAxisAlignment
需要提一下,在Row
和Column
中有主轴和交叉轴这两个东西,这两个东西可以辅助我们更方便的布局,先来看个只有主轴mainAxisAlignment
的代码:
class BoxRowDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.deepPurple,
alignment: Alignment(0.0,0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Container(
color: Colors.red,
width: 80,
height: 80,
),
Container(
color: Colors.green,
width: 60,
height: 60,
),
Container(
color: Colors.blue,
width: 100,
height: 100,
)
],
),
);
}
看几个不同的主轴值运行效果图,图中白色线条和数字用来辅助解释,这样可以更直观的看到每个值的作用:
主轴的属性值有:
-
start
:主方向的开始处对齐(Row对应x轴,Column对应y轴) -
end
:主方向的结束处对齐 -
center
: 主方向的中间处对齐 -
spaceBetween
: 主方向的剩余空间均匀分布在子项的中间 -
spaceAround
: 所有子项均分主轴空间,子项周围留空 -
spaceEvenly
: 主方向的剩余空间均匀分布在子项的中间和两头
交叉轴crossAxisAlignment
我们就来个简单的示例:
class BoxRowDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.deepPurple,
alignment: Alignment(0.0,0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
color: Colors.red,
width: 80,
height: 80,
),
Container(
color: Colors.green,
width: 60,
height: 60,
),
Container(
color: Colors.blue,
width: 100,
height: 100,
)
],
),
);
}
看下运行效果图:
交叉轴的枚举值有:
-
start
: 交叉轴方向顶部对齐 (Row对应y轴,Column对应x轴) -
end
: 交叉轴方向底部对齐 -
center
: 交叉轴方向中部对齐 -
stretch
: 交叉轴方向直接拉伸填充 -
baseline
: 这个需要和textbaseline
一起配合生效,下面会来个示例
class BoxBaseLineDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: <Widget>[
Container(
child: Text(
'足记',
style: TextStyle(fontSize: 15),
),
color: Colors.red,
height:40,
),
Container(
child: Text(
'Fotoplace',
style: TextStyle(fontSize: 60),
),
color: Colors.purple,
height: 80,
),
Container(
child: Text(
'Box',
style: TextStyle(fontSize: 30),
),
color: Colors.blue,
height: 80,
),
],
);
}
}
看一下运行效果就非常直接的看到作用,方便的将文字底部对齐了:
还有一个
Expanded
来一个示例:
class BoxExpandedDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: <Widget>[
Expanded(
child: Container(
child: Text(
'足记',
style: TextStyle(fontSize: 15),
),
color: Colors.red,
height:40,
),
),
Expanded(
child: Container(
child: Text(
'Fotoplace',
style: TextStyle(fontSize: 60),
),
color: Colors.purple,
// height: 80,
),
),
Expanded(
child: Container(
child: Text(
'Box',
style: TextStyle(fontSize: 30),
),
color: Colors.blue,
height: 80,
),
),
],
);
}
}
看一下运行效果:
如果用
Expanded
也就意味着主轴方向不会有空余空间,一定会被子项分完,也有部分Expanded,部分非Expanded的子项,大家可以自行尝试尝试。
3. Column
上面的Row
说清楚之后,Column
就相对来说很简单了直接上个代码,改改值,自己看看效果就可以了:
class BoxColumnDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.deepPurple,
alignment: Alignment(0.0,0.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
color: Colors.red,
width: 80,
height: 80,
),
Container(
color: Colors.green,
width: 60,
height: 60,
),
Container(
color: Colors.blue,
width: 100,
height: 100,
)
],
),
);
}
}
4. Stack
Stack
布局适合重叠式布局,来个带有位置Positioned
的Stack布局示例:
class BoxStackDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
child: Container(
color: Colors.red,
width: 200,
height: 200,
),
),
Positioned(
right: 0,
child: Container(
color: Colors.green,
width: 100,
height: 100,
),
),
Positioned(
left: 10,
top: 30,
child: Container(
color: Colors.blue,
width: 50,
height: 50,
),
),
],
);
}
}
看一下运行结果,你会发现跟iOS中frame甚至只autolayout非常的像,在Stack布局中Positioned
是经常会被用到的一个组件:
5. AspectRatio
AspectRatio
主要用来设置一个比例,来一个示例看一下:
class BoxAspectRatioDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.purple,
alignment: Alignment(0.0,0.0),
child: Container(
color: Colors.blue,
width: 168,
child: AspectRatio(
aspectRatio: 1/1,
child: Icon(Icons.add,),
),
)
);
}
}
可以方便的设置子项的一个比例大小,在根据屏幕大小的布局中会用得到。
无论在Flutter中的布局还是其他的布局,这个东西不是一篇文章就能够说的清楚的,这里只是简答的写了些基本的作用,我们在后面的不断开发中会不停的练习,用这些基本的布局完成美工高规格要求的UI。所有的代码都可以在Github:BoxJ/Flutter-daydayup中下载,本篇代码的文件夹是
boxdemo_003
,欢迎一起交流!
网友评论