03_布局系统
Flutter 布局系统和常用布局组件
Flutter 的布局核心是 Row(水平)和 Column(垂直),对应 CSS Flexbox。没有独立 CSS 文件,样式完全通过 Widget 属性描述。
Row / Column 对应 CSS Flexbox
| CSS Flexbox | Flutter |
|---|---|
display: flex; flex-direction: row |
Row |
display: flex; flex-direction: column |
Column |
justify-content |
mainAxisAlignment |
align-items |
crossAxisAlignment |
flex: 1 |
Expanded(flex: 1) |
gap: 16px |
子项间插入 SizedBox(width/height: 16) |
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // justify-content
crossAxisAlignment: CrossAxisAlignment.center, // align-items
children: [
Text('左'),
Text('中'),
Text('右'),
],
)
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch, // 子元素撑满宽度
children: [
Text('第一行'),
const SizedBox(height: 12), // 行间距(类似 gap 或 margin-bottom)
Text('第二行'),
const SizedBox(height: 12),
Text('第三行'),
],
)
mainAxisAlignment 速查(对应 justify-content):
| Flutter | CSS |
|---|---|
start |
flex-start |
center |
center |
end |
flex-end |
spaceBetween |
space-between |
spaceEvenly |
space-evenly |
spaceAround |
space-around |
Expanded 和 Flexible(对应 flex)
Row(
children: [
// Expanded:占满剩余空间(类似 flex: 1)
Expanded(
flex: 2, // 占 2/3
child: Container(color: Colors.blue, height: 50),
),
Expanded(
flex: 1, // 占 1/3
child: Container(color: Colors.red, height: 50),
),
],
)
// Flexible:最多占指定比例,内容不足时可缩小(类似 flex-shrink)
Row(
children: [
Flexible(child: Text('可被压缩的长文字内容...')),
const Icon(Icons.info),
],
)
Stack(对应 position: absolute)
// Stack = CSS position: relative 的父容器
// Positioned = CSS position: absolute 的子元素
Stack(
children: [
// 底层:背景图
Image.network(
'https://example.com/bg.jpg',
width: double.infinity,
height: 200,
fit: BoxFit.cover,
),
// 渐变遮罩层
Container(
height: 200,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Colors.transparent, Colors.black54],
),
),
),
// 定位文字(类似 position: absolute; bottom: 16; left: 16)
const Positioned(
bottom: 16,
left: 16,
child: Text(
'图片标题',
style: TextStyle(color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold),
),
),
],
)
SizedBox 和 Spacer
// SizedBox:固定尺寸空白,常用于间距
SizedBox(width: 16) // 水平间距(Row 中用)
SizedBox(height: 12) // 垂直间距(Column 中用)
SizedBox(width: 200, height: 100, child: someWidget) // 固定尺寸容器
// Spacer:弹性填充剩余空间(类似 flex: 1 的空白块)
Row(
children: [
Text('左侧内容'),
const Spacer(), // 撑开中间空白
Text('右侧内容'), // 自然右对齐
],
)
Padding 和 Center
// Padding:仅添加内边距(比 Container 更轻量)
Padding(
padding: const EdgeInsets.all(16),
child: Text('内容'),
)
// Center:居中子元素(类似 CSS flex + justify/align center)
Center(child: Text('居中'))
// Align:指定对齐
Align(
alignment: Alignment.bottomRight,
child: Text('右下角'),
)
// EdgeInsets 速查
EdgeInsets.all(16) // 四边均为 16
EdgeInsets.symmetric(horizontal: 20, vertical: 10) // 左右 20,上下 10
EdgeInsets.only(top: 8, left: 16) // 指定方向
EdgeInsets.fromLTRB(16, 8, 16, 8) // 完全自定义
Wrap(自动换行,类似 flex-wrap)
// 类比 CSS flex-wrap: wrap
Wrap(
spacing: 8, // 主轴间距(类似 column-gap)
runSpacing: 8, // 交叉轴间距(类似 row-gap)
children: ['Flutter', 'Dart', 'Mobile', 'iOS', 'Android'].map((tag) =>
Chip(
label: Text(tag),
backgroundColor: Colors.blue.shade100,
),
).toList(),
)
ConstrainedBox / FractionallySizedBox(尺寸约束)
// ConstrainedBox:限制子 Widget 的最小/最大尺寸(类似 min-width / max-width)
ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 100,
maxWidth: 300,
minHeight: 48,
),
child: ElevatedButton(onPressed: () {}, child: const Text('按钮')),
)
// FractionallySizedBox:按父容器百分比设置尺寸(类似 width: 80%)
FractionallySizedBox(
widthFactor: 0.8, // 占父容器宽度的 80%
child: ElevatedButton(onPressed: () {}, child: const Text('80% 宽按钮')),
)
// SizedBox.expand():占满父容器(类似 width: 100%; height: 100%)
SizedBox.expand(
child: Container(color: Colors.blue),
)
// width: double.infinity = width: 100%(最常用写法)
Container(
width: double.infinity,
child: ElevatedButton(onPressed: () {}, child: const Text('全宽按钮')),
)