Flutter学习--布局之Row/Column/Stack
Flutter中布局以 Row Column Stack 为主
一.Alignment
一般来说,Align的使用都是其他控件的一个参数,目的是为了设置子child的对齐方式,比如居中,左上,右下等多个对齐方向,其本身用法也多灵活。
如Alignment(0.0,0.0) == Alignment.center ,都是将子child居中对齐的控制方式
一个栗子🌰
根据设置aliginment参数的值可以调整子child的位置
class LayoutDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.yellow,
alignment: Alignment(-1, 0),//
child: Text(
'泥猴桃',
style: TextStyle(fontSize: 28,color: Colors.red),
),
);
}
}
图片.png
二.Row Cloumn Stack
1.Row(横向)
在Flutter中非常常见的一个多子节点控件,将children排列成一行。
例子:
class LayoutDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.yellow,
alignment: Alignment(0, 0),//
child: Row(
children: <Widget>[
Container(width: 50,height: 50,color: Colors.red,),
Container(width: 50,height: 50,color: Colors.blue,),
Container(width: 50,height: 50,color: Colors.white,),
],
)
);
}
}
实现效果为
图片.png
mainAxisAlignment(主轴)
在水平方向控件如Row中MainAxisAlignment(主轴)就是与当前控件方向一致的轴,而CrossAxisAlignment(交叉轴)就是与当前控件方向垂直的轴
它是一个枚举值
enum MainAxisAlignment {
//将子控件放在主轴的开始位置
start,
//将子控件放在主轴的结束位置
end,
//将子控件放在主轴的中间位置
center,
//将主轴空白位置进行均分,排列子元素,手尾没有空隙
spaceBetween,
//将主轴空白区域均分,使中间各个子控件间距相等,首尾子控件间距为中间子控件间距的一半
spaceAround,
//将主轴空白区域均分,使各个子控件间距相等
spaceEvenly,
}
我们可以写三个组件一一调试一下 spaceBetween
class LayoutDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.yellow,
alignment: Alignment(0, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
// crossAxisAlignment: Cro,
children: <Widget>[
Container(
width: 100,
height: 100,
color: Colors.red,
child: Text(
'1',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 60),
)),
Container(
width: 100,
height: 100,
color: Colors.blue,
child: Text(
'2',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 60),
)),
Container(
width: 100,
height: 100,
color: Colors.white,
child: Text(
'3',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 60),
)),
],
));
}
}
效果如下
图片.png
添加
textDirection: TextDirection.rtl
可以改变MainAxisAlignment的起始位置和排列方向
图片.png
crossAxisAlignment(交叉轴)
CrossAxisAlignment是垂直的,默认起始位置在中间,排列方向为从上至下,此时可以通过verticalDirection来改变CrossAxisAlignment的起始位置及排列方向
枚举值有:
enum CrossAxisAlignment {
//将子控件放在交叉轴的起始位置
start,
//将子控件放在交叉轴的结束位置
end,
//将子控件放在交叉轴的中间位置
center,
//使子控件填满交叉轴
stretch,
//将子控件放在交叉轴的上,并且与基线相匹配(不常用)
baseline,
}
这里注意baselin需要与子控件的约束一起使用,不能单独使用,否则会报错。
添加
verticalDirection: VerticalDirection.up,
效果如下
图片.png
可以改变CrossAxisAlignment的起始位置及排列方向
2.Cloumn
跟Row很相似,这里就不赘述了
3.Stack
这个组件跟iOS中的布局方式很像,子视图按层级叠加。
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情况还是比较好理解的,下面会详细讲解的
fit :用来决定没有Positioned方式时候子Widget的大小,StackFit.loose 指的是子Widget 多大就多大,StackFit.expand使子Widget的大小和父组件一样大
overflow :指子Widget 超出Stack时候如何显示,默认值是Overflow.clip,子Widget超出Stack会被截断
Positioned
这个使用控制Widget的位置,通过他可以随意摆放一个组件,有点像绝对布局
Positioned({
Key key,
this.left,
this.top,
this.right,
this.bottom,
this.width,
this.height,
@required Widget child,
})
left、top 、right、 bottom分别代表离Stack左、上、右、底四边的距离
class StackDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment(0, 0),
color: Colors.yellowAccent,
child: Stack(
alignment: Alignment(0, 0),
children: <Widget>[
Positioned(
right: 0,//距离左边距为0
child: Container(
color: Colors.white,
width: 200,
height: 200,
),
),
Positioned(
left: 0,//距离右边距为0
child: Container(
color: Colors.green,
width: 100,
height: 100,
),
),
Positioned(
right: 250,//距离右边距为0
child: Container(
color: Colors.blue,
width: 50,
height: 50,
),
),
],
),
);
}
}
效果如下
图片.png
AspectRatio
设置控件的宽高比
如下,设置控件的宽度,经过计算可得到控件的高度为100
class LayoutDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
// alignment: Alignment(0, 0),
width: 200,
child: AspectRatio(
aspectRatio: 2/1,
// child: Container(
// ),
)
);
}
}
效果如下
图片.png
三.Expanded(填充式布局/灵活布局)
源码如下
class Expanded extends Flexible {
const Expanded({
Key key,
int flex = 1,
@required Widget child,
}) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);
}
举个例子
class LayoutDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.yellow,
alignment: Alignment(0, 0), //
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.ideographic,
textDirection: TextDirection.ltr,
verticalDirection: VerticalDirection.up,
children: <Widget>[
Expanded(child: Container(
width: 80,
height: 80,
color: Colors.red,
child: Text(
'hahah',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 60),
)),
),
Expanded(child: Container(
width: 120,
height: 120,
color: Colors.blue,
child: Text(
'xixixi',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 60),
)),
),
Expanded(child: Container(
width: 160,
height: 160,
color: Colors.white,
child: Text(
'yoyoyo',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 60),
)),
),
],
));
}
}
实现效果为
图片.png