线性布局
线性布局是最常用的布局方式,让子组件沿水平方向(Row)或垂直方向(Column)排列。
Column — 垂直排列
Column 让子组件从上到下排列。
常用属性
dart
Column({
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, // 主轴对齐(垂直)
MainAxisSize mainAxisSize = MainAxisSize.max, // 主轴大小
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, // 交叉轴对齐(水平)
TextDirection? textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
List<Widget> children = const <Widget>[],
})基本用法
dart
import 'package:flutter/material.dart';
class ColumnBasicExample extends StatelessWidget {
const ColumnBasicExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Column 基本用法')),
// ─── ★ Column 垂直排列 ──────────────
body: const Column(
children: [
Text('第一行'),
Text('第二行'),
Text('第三行'),
],
),
// ─── ☆ Column 垂直排列 ──────────────
);
}
}主轴对齐(mainAxisAlignment)
dart
import 'package:flutter/material.dart';
class MainAxisAlignmentExample extends StatelessWidget {
const MainAxisAlignmentExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('主轴对齐')),
body: Column(
// ─── ★ 主轴对齐方式 ──────────────
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// ─── ☆ 主轴对齐方式 ──────────────
children: const [
Text('第一行'),
Text('第二行'),
Text('第三行'),
],
),
);
}
}各值效果说明:
| 值 | 效果 |
|---|---|
MainAxisAlignment.start | 从顶部开始(默认) |
MainAxisAlignment.center | 居中 |
MainAxisAlignment.end | 底部 |
MainAxisAlignment.spaceEvenly | 等间距(含两端) |
MainAxisAlignment.spaceAround | 等间距(两端减半) |
MainAxisAlignment.spaceBetween | 两端贴边,中间等间距 |
交叉轴对齐(crossAxisAlignment)
dart
import 'package:flutter/material.dart';
class CrossAxisAlignmentExample extends StatelessWidget {
const CrossAxisAlignmentExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('交叉轴对齐')),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start, // 尝试替换为 center / end / stretch
children: const [
Text('短文本'),
Text('这是一段比较长的文本'),
Text('中等'),
],
),
);
}
}各值效果说明:
| 值 | 效果 |
|---|---|
CrossAxisAlignment.start | 左对齐 |
CrossAxisAlignment.center | 居中(默认) |
CrossAxisAlignment.end | 右对齐 |
CrossAxisAlignment.stretch | 拉伸填满 |
Row — 水平排列
Row 让子组件从左到右排列。属性与 Column 完全相同,只是主轴方向不同(水平 vs 垂直)。
基本用法
dart
import 'package:flutter/material.dart';
class RowBasicExample extends StatelessWidget {
const RowBasicExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Row 基本用法')),
body: const Row(
children: [
Icon(Icons.star),
SizedBox(width: 8),
Text('收藏'),
],
),
);
}
}对齐方式
dart
Row(
mainAxisAlignment: MainAxisAlignment.center, // 水平居中
crossAxisAlignment: CrossAxisAlignment.center, // 垂直居中
children: const [Text('居中内容')],
)常见模式
dart
import 'package:flutter/material.dart';
class RowPatternsExample extends StatelessWidget {
const RowPatternsExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Row 常见模式')),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 左右分布(如:标题 + 操作按钮)
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('标题'),
IconButton(icon: const Icon(Icons.more_vert), onPressed: () {}),
],
),
const SizedBox(height: 16),
// 图标 + 文字 + 间距
Row(
children: [
Icon(Icons.location_on, size: 16, color: Colors.grey[600]),
const SizedBox(width: 4),
Text('北京市', style: TextStyle(color: Colors.grey[600])),
],
),
],
),
);
}
}Expanded / Flexible — 弹性分配
当需要让子组件按比例分配剩余空间时,使用 Expanded 或 Flexible。
Expanded — 占满剩余空间
dart
import 'package:flutter/material.dart';
class ExpandedExample extends StatelessWidget {
const ExpandedExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Expanded 示例')),
body: Row(
children: [
Container(width: 50, color: Colors.red),
Expanded(
child: Container(color: Colors.blue, child: const Center(child: Text('剩余空间'))),
),
],
),
);
}
}flex 参数 — 按比例分配
dart
import 'package:flutter/material.dart';
class FlexExample extends StatelessWidget {
const FlexExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Flex 按比例分配')),
body: Row(
children: [
Expanded(
flex: 1,
child: Container(color: Colors.red, child: const Center(child: Text('1份'))),
),
Expanded(
flex: 2,
child: Container(color: Colors.blue, child: const Center(child: Text('2份'))),
),
],
),
);
}
}
// 红色占 1/3,蓝色占 2/3Expanded vs Flexible
| Expanded | Flexible | |
|---|---|---|
| 行为 | 必须填满剩余空间 | 可以不填满(根据子组件大小) |
| fit 参数 | 无(相当于 FlexFit.tight) | FlexFit.loose(默认)/ FlexFit.tight |
| 典型场景 | 列表项左右分布 | 子组件有固定大小时 |
dart
import 'package:flutter/material.dart';
class ExpandedVsFlexible extends StatelessWidget {
const ExpandedVsFlexible({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Expanded vs Flexible')),
body: Column(
children: [
const Text('Expanded:子组件被强制拉伸'),
Row(
children: [
Expanded(child: Container(color: Colors.red[100], child: const Text('短'))),
Expanded(child: Container(color: Colors.blue[100], child: const Text('比较长的文字'))),
],
),
const SizedBox(height: 16),
const Text('Flexible(loose):子组件不被强制拉伸'),
Row(
children: [
Flexible(child: Container(color: Colors.red[100], child: const Text('短'))),
Flexible(child: Container(color: Colors.blue[100], child: const Text('比较长的文字'))),
],
),
],
),
);
}
}Align / Center — 对齐
Center — 居中
Center 是 Align 的特例,等价于 Alignment.center。
dart
import 'package:flutter/material.dart';
class CenterExample extends StatelessWidget {
const CenterExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: const Text('居中文字'),
),
);
}
}Align — 任意位置对齐
dart
import 'package:flutter/material.dart';
class AlignExample extends StatelessWidget {
const AlignExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Align(
alignment: Alignment.topLeft, // 尝试替换为 topRight / bottomCenter / Alignment(0.5, 0.5)
child: Container(
color: Colors.blue,
padding: const EdgeInsets.all(16),
child: const Text('对齐文字'),
),
),
);
}
}常用对齐值
| Alignment 常量 | 位置 |
|---|---|
topLeft | 左上 |
topCenter | 上中 |
topRight | 右上 |
centerLeft | 左中 |
center | 正中 |
centerRight | 右中 |
bottomLeft | 左下 |
bottomCenter | 下中 |
bottomRight | 右下 |
Wrap — 自动换行
当子组件在主轴上放不下时,Wrap 会自动换行(类似 CSS 的 flex-wrap)。
基本用法
dart
import 'package:flutter/material.dart';
class WrapExample extends StatelessWidget {
const WrapExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Wrap 自动换行')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Wrap(
spacing: 8, // 水平间距
runSpacing: 8, // 垂直间距(换行间距)
alignment: WrapAlignment.start,
children: const [
Chip(label: Text('标签1')),
Chip(label: Text('标签2')),
Chip(label: Text('标签3')),
Chip(label: Text('标签4')),
Chip(label: Text('标签5')),
],
),
),
);
}
}常用属性
| 属性 | 说明 | 默认值 |
|---|---|---|
direction | 排列方向 | Axis.horizontal |
spacing | 主轴间距 | 0.0 |
runSpacing | 交叉轴间距 | 0.0 |
alignment | 主轴对齐 | WrapAlignment.start |
crossAxisAlignment | 交叉轴对齐 | WrapCrossAlignment.start |
Row 溢出 vs Wrap 自动换行
dart
import 'package:flutter/material.dart';
class OverflowVsWrap extends StatelessWidget {
const OverflowVsWrap({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Row 溢出 vs Wrap 换行')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('✅ Wrap 自动换行:', style: TextStyle(fontWeight: FontWeight.bold)),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
Container(width: 200, height: 50, color: Colors.red),
Container(width: 200, height: 50, color: Colors.blue),
Container(width: 200, height: 50, color: Colors.green),
],
),
const SizedBox(height: 16),
const Text('❌ Row 溢出报错(内容太多放不下),不要这样写!'),
],
),
),
);
}
}线性布局速查
| 需求 | 组件 |
|---|---|
| 垂直排列 | Column |
| 水平排列 | Row |
| 子组件占满剩余空间 | Expanded |
| 子组件按比例分配 | Expanded(flex: n) |
| 居中显示 | Center |
| 任意位置对齐 | Align |
| 自动换行 | Wrap |
| 组件间间距 | SizedBox |
