所谓线性布局,即指沿水平或垂直方向排列子组件。Flutter 中通过Row
和Column
来实现线性布局。
主轴和纵轴
对于线性布局,有主轴和纵轴之分,如果布局是沿水平方向,那么主轴就是指水平方向,而纵轴即垂直方向;如果布局沿垂直方向,那么主轴就是指垂直方向,而纵轴就是水平方向。
一、Row组件
1.1 Row介绍
Row 组件用于将所有的子 Widget 排成一行。从源码中查看 Row 的属性:
Row({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, // 主轴对齐方式
MainAxisSize mainAxisSize = MainAxisSize.max, // 水平方向尽可能大
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, // 交叉处对齐方式
TextDirection textDirection, // 水平方向子widget的布局顺序(默认为系统当前Locale环境的文本方向(如中文、英语都是从左往右,而阿拉伯语是从右往左))
VerticalDirection verticalDirection = VerticalDirection.down, // 表示Row纵轴(垂直)的对齐方向
TextBaseline textBaseline, // 如果上面是baseline对齐方式,那么选择什么模式(有两种可选)
List<Widget> children = const <Widget>[],
})
部分属性详细解析:
mainAxisSize:
- 表示Row在主轴(水平)方向占用的空间,默认是
MainAxisSize.max
,表示尽可能多的占用水平方向的空间,此时无论子widgets实际占用多少水平空间,Row 的宽度始终等于水平方向的最大宽度 - 而
MainAxisSize.min
表示尽可能少的占用水平空间,当子 widgets 没有占满水平剩余空间,则Row的实际宽度等于所有子 widgets 占用的的水平空间;
mainAxisAlignment:表示子 Widgets 在 Row 所占用的水平空间内对齐方式
- 如果mainAxisSize值为
MainAxisSize.min
,则此属性无意义,因为子 widgets 的宽度等于 Row 的宽度 - 只有当mainAxisSize的值为
MainAxisSize.max
时,此属性才有意义 MainAxisAlignment.start
表示沿 textDirection 的初始方向对齐,- 如textDirection取值为
TextDirection.ltr
时,则MainAxisAlignment.start
表示左对齐,textDirection取值为TextDirection.rtl
时表示从右对齐。 - 而
MainAxisAlignment.end
和MainAxisAlignment.start
正好相反; MainAxisAlignment.center
表示居中对齐。
crossAxisAlignment:表示子 Widgets 在纵轴方向的对齐方式
- Row 的高度等于子 Widgets 中最高的子元素高度
- 它的取值和 MainAxisAlignment 一样(包含
start
、end
、center
三个值) - 不同的是 crossAxisAlignment 的参考系是 verticalDirection,即 verticalDirection 值为
VerticalDirection.down
时crossAxisAlignment.start
指顶部对齐,verticalDirection 值为VerticalDirection.up
时,crossAxisAlignment.start
指底部对齐;而crossAxisAlignment.end
和crossAxisAlignment.start
正好相反;
1.2 Row演练
我们来对部分属性进行简单的代码演练,其他一些属性大家自己学习一下
class MyHomeBody extends StatelessWidget {
const MyHomeBody({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(color: Colors.red, width: 60, height: 60),
Container(color: Colors.blue, width: 80, height: 80),
Container(color: Colors.green, width: 70, height: 70),
Container(color: Colors.orange, width: 100, height: 100),
],
);
}
}
效果图如下:
1.3 mainAxisSize
默认情况下,Row 会尽可能占据多的宽度,让子 Widget 在其中进行排布,这是因为 mainAxisSize 属性默认值是MainAxisSize.max
。
我们来看一下,如果这个值被修改为MainAxisSize.max
会什么变化:
二、Column组件
Column 组件用于将所有的子 Widget 排成一列,学会了前面的 Row 后,Column 只是和 row 的方向不同而已。
2.1 Column介绍
我们直接看它的源码:我们发现和 Row 属性是一致的,不再解释
Column({
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>[],
})
2.2 Column演练
我们直接将Row的代码中Row改为Column,查看代码运行效果:
class MyHomeBody extends StatelessWidget {
const MyHomeBody({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
flex: 1,
child: Container(color: Colors.red, width: 60),
),
Container(color: Colors.blue, width: 80, height: 80),
Container(color: Colors.green, width: 70, height: 70),
Expanded(
flex: 1,
child: Container(color: Colors.orange, width: 100),
)
],
);
}
}
效果图如下:
标签:MainAxisSize,Column,布局,crossAxisAlignment,对齐,MainAxisAlignment,Flutter,Row From: https://www.cnblogs.com/linuxAndMcu/p/18458608