快速决策流程图
scss
复制代码
需要布局?
├─ 只有一个子组件?
│ ├─ 需要居中? → Center
│ ├─ 需要边距? → Padding
│ ├─ 需要背景/边框/圆角? → Container
│ ├─ 需要固定大小? → SizedBox
│ ├─ 需要特定对齐? → Align
│ └─ 需要保持宽高比? → AspectRatio
│
└─ 有多个子组件?
├─ 横向排列? → Row
├─ 纵向排列? → Column
├─ 重叠显示? → Stack
├─ 自动换行? → Wrap
├─ 网格显示? → GridView
├─ 列表显示? → ListView
└─ 内容超出屏幕? → SingleChildScrollView
场景化选择指南
1. 基础样式场景
需要设置背景色、圆角、阴影、边框
less
复制代码
// ✅ 使用 Container
Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(12),
boxShadow: [BoxShadow(color: Colors.grey, blurRadius: 4)],
),
child: Text('内容'),
)
只需要边距
less
复制代码
// ✅ 使用 Padding(更轻量)
Padding(
padding: EdgeInsets.all(16),
child: Text('内容'),
)
// ❌ 避免用 Container(过重)
Container(
padding: EdgeInsets.all(16),
child: Text('内容'),
)
需要固定间距
less
复制代码
// ✅ 使用 SizedBox
Column(
children: [
Text('第一行'),
SizedBox(height: 16), // 间距
Text('第二行'),
],
)
2. 排列布局场景
横向排列(如工具栏、按钮组)
less
复制代码
// ✅ 使用 Row
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(Icons.menu),
Text('标题'),
Icon(Icons.search),
],
)
纵向排列(如表单、卡片内容)
less
复制代码
// ✅ 使用 Column
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('姓名'),
TextField(),
SizedBox(height: 16),
Text('邮箱'),
TextField(),
],
)
子组件需要自适应分配空间
less
复制代码
// ✅ 使用 Expanded 或 Flexible
Row(
children: [
Icon(Icons.star),
Expanded( // 占据剩余空间
child: Text('这是一段很长的文本...'),
),
Icon(Icons.more_vert),
],
)
3. 特殊排列场景
标签云、流式布局(自动换行)
less
复制代码
// ✅ 使用 Wrap
Wrap(
spacing: 8,
runSpacing: 8,
children: [
Chip(label: Text('Flutter')),
Chip(label: Text('Dart')),
Chip(label: Text('Mobile')),
// 自动换行
],
)
图片上叠加按钮、角标
less
复制代码
// ✅ 使用 Stack + Positioned
Stack(
children: [
Image.network('url'),
Positioned(
top: 8,
right: 8,
child: Icon(Icons.favorite, color: Colors.red),
),
],
)
4. 列表场景
少量固定项目(<20项)
less
复制代码
// ✅ 使用 Column(简单直接)
Column(
children: [
ListTile(title: Text('项目1')),
ListTile(title: Text('项目2')),
ListTile(title: Text('项目3')),
],
)
大量动态数据
less
复制代码
// ✅ 使用 ListView.builder(性能优化)
ListView.builder(
itemCount: 1000,
itemBuilder: (context, index) {
return ListTile(title: Text('项目 $index'));
},
)
横向滚动列表
less
复制代码
// ✅ 使用 ListView + scrollDirection
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (context, index) {
return Container(
width: 150,
child: Card(child: Text('卡片 $index')),
);
},
)
网格布局
less
复制代码
// ✅ 固定列数用 GridView.count
GridView.count(
crossAxisCount: 2,
children: List.generate(20, (index) => Card()),
)
// ✅ 固定宽度用 GridView.extent
GridView.extent(
maxCrossAxisExtent: 150, // 每项最大宽度
children: List.generate(20, (index) => Card()),
)
5. 滚动场景
单个组件需要滚动
less
复制代码
// ✅ 使用 SingleChildScrollView
SingleChildScrollView(
child: Column(
children: [
// 很多内容
],
),
)
列表需要滚动
scss
复制代码
// ✅ ListView 自带滚动
ListView(children: [...])
// ❌ 不需要额外包裹 SingleChildScrollView
避免嵌套滚动冲突
less
复制代码
// ✅ ListView 内使用 shrinkWrap
Column(
children: [
Text('标题'),
ListView.builder(
shrinkWrap: true, // 重要!
physics: NeverScrollableScrollPhysics(), // 禁用内部滚动
itemCount: 10,
itemBuilder: (context, index) => ListTile(),
),
],
)
6. 对齐场景
单个组件居中
less
复制代码
// ✅ 使用 Center(最简单)
Center(child: Text('居中文本'))
// ✅ 或使用 Align(更灵活)
Align(
alignment: Alignment.center,
child: Text('居中文本'),
)
多个组件整体居中
less
复制代码
// ✅ 使用 Center 包裹 Column/Row
Center(
child: Column(
mainAxisSize: MainAxisSize.min, // 重要!
children: [
Text('标题'),
Text('副标题'),
],
),
)
Row/Column 内部对齐
less
复制代码
// ✅ 使用对齐属性
Column(
mainAxisAlignment: MainAxisAlignment.center, // 主轴居中
crossAxisAlignment: CrossAxisAlignment.start, // 交叉轴起始
children: [...],
)
7. 响应式场景
根据屏幕宽度调整布局
scss
复制代码
// ✅ 使用 LayoutBuilder
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 600) {
return Row(children: [侧边栏, 内容]); // 平板/桌面
} else {
return Column(children: [内容]); // 手机
}
},
)
适配安全区域(刘海屏、底部栏)
less
复制代码
// ✅ 使用 SafeArea
SafeArea(
child: Column(children: [...]),
)
常见错误与优化
❌ 错误示例 1:过度使用 Container
less
复制代码
// ❌ 只需要边距,却用 Container
Container(
padding: EdgeInsets.all(16),
child: Text('内容'),
)
// ✅ 应该用 Padding
Padding(
padding: EdgeInsets.all(16),
child: Text('内容'),
)
❌ 错误示例 2:不必要的嵌套
less
复制代码
// ❌ 多层无意义嵌套
Container(
child: Center(
child: Container(
child: Text('内容'),
),
),
)
// ✅ 简化
Center(child: Text('内容'))
❌ 错误示例 3:Column 超出屏幕未处理
less
复制代码
// ❌ 内容多时会溢出
Column(
children: [
// 很多内容
],
)
// ✅ 添加滚动
SingleChildScrollView(
child: Column(children: [...]),
)
❌ 错误示例 4:ListView 内嵌套 ListView
less
复制代码
// ❌ 会报错或性能差
ListView(
children: [
ListView(children: [...]), // 错误!
],
)
// ✅ 使用 shrinkWrap
ListView(
children: [
ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: [...],
),
],
)
性能优化建议
- 大列表必须用 .builder :超过 20 项就用
ListView.builder 或 GridView.builder
- 避免深层嵌套:超过 5 层考虑拆分成独立 Widget
- 合理使用 const :静态 Widget 加
const 提升性能
- 避免在 build 中创建大量对象:把样式定义提取到常量
- 使用
RepaintBoundary:隔离频繁重绘的组件
less
复制代码
// ✅ 性能优化示例
const EdgeInsets _padding = EdgeInsets.all(16); // 复用常量
ListView.builder( // 大列表用 builder
itemCount: 1000,
itemBuilder: (context, index) {
return RepaintBoundary( // 隔离重绘
child: const ListTile(title: Text('项目')), // 使用 const
);
},
)
快速记忆口诀
- 单个组件:居中 Center,边距 Padding,样式 Container
- 横向排列:Row + Expanded
- 纵向排列:Column + Expanded
- 层叠覆盖:Stack + Positioned
- 自动换行:Wrap 最方便
- 列表滚动:ListView.builder 性能好
- 网格展示:GridView.count 列数定
- 内容太多:SingleChildScrollView 包一包