Flutter 线性组件详解
在 Flutter 中,**线性组件(Linear Widgets)**通常指的是那些按照 水平(横向)或垂直(纵向)方向依次排列子组件 的布局组件。它们是构建用户界面最基础、最常用的布局工具之一。
最常见的线性组件有:
这两个组件都是 Flex 布局的特例 ,属于 一维线性布局,只能在一个方向上排列子组件。
一、线性布局的基本概念
线性布局 是指子组件沿着一条直线(水平或垂直)依次排列的布局方式。
- Row :子组件 从左到右 水平排列(主轴为水平方向)。
- Column :子组件 从上到下 垂直排列(主轴为垂直方向)。
它们都继承自 Flex ,因此具有相似的属性,比如 mainAxisAlignment、crossAxisAlignment、mainAxisSize等。
二、Row(水平线性布局)
1. 基本用法
dart
Row(
children: [
Icon(Icons.star),
Text('Flutter'),
Icon(Icons.favorite),
],
)
- 子组件会 从左到右 依次排列。
- 如果子组件总宽度超过屏幕,默认情况下会溢出(显示黄色黑条警告)。
2. 主要属性详解
| 属性 | 类型 | 说明 |
|---|---|---|
| children | List<Widget> |
子组件列表,按顺序排列 |
| mainAxisAlignment | MainAxisAlignment |
主轴(水平方向)对齐方式,控制子组件在 Row 的水平方向如何排列(如居中、两端对齐等) |
| crossAxisAlignment | CrossAxisAlignment |
交叉轴(垂直方向)对齐方式,控制子组件在垂直方向如何对齐(如顶部对齐、居中对齐等) |
| mainAxisSize | MainAxisSize |
主轴方向占用空间的大小:MainAxisSize.max(默认,占满可用空间)、MainAxisSize.min(仅包裹内容) |
| textDirection | TextDirection |
文本方向,影响 mainAxisAlignment在 RTL/LTR 下的表现(一般无需手动设置) |
| verticalDirection | VerticalDirection |
垂直方向子组件排序:VerticalDirection.down(默认,从上到下)、VerticalDirection.up(从下到上) |
3. 主轴 & 交叉轴(重要概念)
- 主轴(Main Axis) :Row 的主轴是 水平方向(从左到右)。
- 交叉轴(Cross Axis) :与主轴垂直的方向,对于 Row 来说是 垂直方向(从上到下)。
| 对齐属性 | 说明 | 常用值 |
|---|---|---|
| mainAxisAlignment(主轴对齐) | 控制子组件在 水平方向 如何排列 | start(默认,左对齐)、center(居中)、end(右对齐)、spaceBetween(两端对齐,中间平均分布)、spaceAround、spaceEvenly |
| crossAxisAlignment(交叉轴对齐) | 控制子组件在 垂直方向 如何对齐 | start(顶部对齐)、center(垂直居中)、end(底部对齐)、stretch(撑满高度)、baseline(基线对齐) |
4. 示例代码
dart
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 水平均匀分布
crossAxisAlignment: CrossAxisAlignment.center, // 垂直居中
mainAxisSize: MainAxisSize.max, // 占满宽度
children: [
Icon(Icons.home, size: 30),
Icon(Icons.search, size: 30),
Icon(Icons.person, size: 30),
],
)
三、Column(垂直线性布局)
1. 基本用法
dart
Column(
children: [
Text('标题'),
Icon(Icons.star),
Text('描述'),
],
)
- 子组件会 从上到下 依次排列。
- 如果子组件总高度超过屏幕,默认也会溢出。
2. 主要属性(与 Row 类似)
| 属性 | 说明 |
|---|---|
| children | 子组件列表,按顺序从上到下排列 |
| mainAxisAlignment | 控制子组件在 垂直方向 的对齐方式(如居中、顶部对齐等) |
| crossAxisAlignment | 控制子组件在 水平方向 的对齐方式(如左对齐、居中等) |
| mainAxisSize | 是否占满垂直方向可用空间:max(默认,占满)、min(仅包裹内容) |
| verticalDirection | 控制子组件排列顺序:down(从上到下,默认)、up(从下到上) |
3. 主轴 & 交叉轴(Column 版)
- 主轴(Main Axis) :Column 的主轴是 垂直方向(从上到下)。
- 交叉轴(Cross Axis) :与主轴垂直,即 水平方向(从左到右)。
| 对齐属性 | 说明 | 常用值 |
|---|---|---|
| mainAxisAlignment | 控制子组件在 垂直方向 如何排列 | start(顶部对齐,默认)、center(垂直居中)、end(底部对齐)、spaceBetween、spaceAround、spaceEvenly |
| crossAxisAlignment | 控制子组件在 水平方向 如何对齐 | start(左对齐)、center(水平居中)、end(右对齐)、stretch(撑满宽度)、baseline(基线对齐) |
4. 示例代码
dart
Column(
mainAxisAlignment: MainAxisAlignment.center, // 垂直居中
crossAxisAlignment: CrossAxisAlignment.start, // 水平左对齐
mainAxisSize: MainAxisSize.max, // 占满整个垂直空间
children: [
Text('用户名', style: TextStyle(fontSize: 16)),
TextField(),
Text('密码', style: TextStyle(fontSize: 16)),
TextField(obscureText: true),
ElevatedButton(onPressed: () {}, child: Text('登录')),
],
)
四、Row 与 Column 的对比
| 特性 | Row | Column |
|---|---|---|
| 排列方向 | 水平(从左到右) | 垂直(从上到下) |
| 主轴 | 水平方向 | 垂直方向 |
| 交叉轴 | 垂直方向 | 水平方向 |
| 适用场景 | 横向排列图标、按钮等 | 竖向排列文本、输入框、表单等 |
| 常见问题 | 水平方向超出屏幕会溢出,可用 Expanded或 Wrap解决 |
垂直方向超出屏幕会溢出,可用 SingleChildScrollView包裹 |
五、常见问题与解决方案
❌ 问题 1:Row 或 Column 中的子组件太多,超出屏幕发生溢出
现象: 出现 黄色黑色溢出条(Overflow)提示。
原因: 子组件总宽度/高度超出了屏幕或父容器范围。
解决方法:
- 使用
Expanded或Flexible包裹子组件,让它们自动填充剩余空间。 - 使用
SingleChildScrollView包裹 Row/Column,使其可以滚动。 - 使用
Wrap替代 Row,让子组件自动换行。
✅ 示例:使用 Expanded 均分空间
dart
Row(
children: [
Expanded( // 占据剩余空间的一部分
child: Container(color: Colors.red, height: 50),
),
Expanded( // 占据剩余空间的一部分
child: Container(color: Colors.blue, height: 50),
),
],
)
✅ 示例:使用 SingleChildScrollView 解决溢出
dart
SingleChildScrollView(
child: Column(
children: List.generate(20, (i) => Text('Item $i\n' * 5)),
),
)
❌ 问题 2:子组件高度/宽度不生效?
原因: 在 Column中,子组件的宽度默认会尽可能大(受限于父容器)。在 Row中,子组件的高度默认会撑满。
如果想控制子组件的对齐或尺寸,可以使用:
crossAxisAlignment(控制交叉轴对齐,如垂直居中)MainAxisSize.min(让 Row/Column 尽量小,不占满)SizedBox/Container包裹设置固定宽高
六、高级用法:结合 Expanded、Flexible、Spacer
1. Expanded:强制撑满剩余空间
dart
Row(
children: [
Icon(Icons.star),
Expanded( // 撑满剩余的水平空间
child: Text('这是一个很长的文本,它会撑满剩余的所有空间'),
),
],
)
2. Flexible:灵活分配空间(可收缩)
与 Expanded类似,但允许子组件不被强制撑满(可收缩)。
dart
Row(
children: [
Flexible(
flex: 1,
child: Container(color: Colors.red, height: 40),
),
Flexible(
flex: 2,
child: Container(color: Colors.green, height: 40),
),
],
)
3. Spacer:插入空白间距
dart
Row(
children: [
Icon(Icons.menu),
Spacer(), // 自动填充空白
Text('标题'),
],
)
七、总结
| 组件 | 作用 | 排列方向 | 主轴方向 | 适用场景 |
|---|---|---|---|---|
| Row | 水平线性布局 | 水平(从左到右) | 水平方向 | 图标 + 文本、按钮组、横向排列等 |
| Column | 垂直线性布局 | 垂直(从上到下) | 垂直方向 | 表单、页面主体布局、竖向排列等 |
核心属性:
mainAxisAlignment→ 主轴对齐(如居中、分散对齐)crossAxisAlignment→ 交叉轴对齐(如垂直居中、左对齐)mainAxisSize→ 是否占满主轴方向空间Expanded/Flexible→ 弹性分配空间Spacer→ 插入空白
八、推荐学习顺序
- 先掌握 Row 和 Column 的基本用法与主轴交叉轴概念。
- 再学习 mainAxisAlignment / crossAxisAlignment 的常用取值和效果。
- 然后了解 Expanded / Flexible / Spacer 的使用场景。
- 最后解决 溢出问题(SingleChildScrollView / Wrap)。