5.1 填充(Padding)
📚 章节概览
欢迎来到第5章:容器类组件!本章第一节将学习 Padding 组件,它是最基础也是最常用的容器类组件之一:
- Padding - 填充组件
- EdgeInsets - 边距设置类
- all - 所有方向相同填充
- only - 指定某个方向填充
- symmetric - 对称方向填充
- fromLTRB - 分别指定四个方向
- 实际应用 - 常见使用场景
🎯 核心知识点
Padding vs Margin
在Flutter中,Padding 用于设置内边距(类似CSS的padding),而外边距通常通过Container的margin属性或者外层Padding来实现。
scss
┌──────────────────┐
│ Margin (外) │ ← Container的margin或外层Padding
│ ┌────────────┐ │
│ │ Padding(内)│ │ ← Padding组件
│ │ ┌──────┐ │ │
│ │ │Child │ │ │ ← 子组件
│ │ └──────┘ │ │
│ └────────────┘ │
└──────────────────┘
1️⃣ Padding(填充组件)
1.1 构造函数
dart
Padding({
Key? key,
required EdgeInsetsGeometry padding,
Widget? child,
})
1.2 主要属性
| 属性 | 类型 | 说明 |
|---|---|---|
padding |
EdgeInsetsGeometry | 填充值(必需) |
child |
Widget? | 子组件 |
1.3 基础用法
dart
Padding(
padding: EdgeInsets.all(16),
child: Text('Hello World'),
)
2️⃣ EdgeInsets(边距设置)
2.1 什么是EdgeInsets
EdgeInsets 是 EdgeInsetsGeometry 的子类,提供了多种便捷方法来设置填充值。
2.2 四个便捷方法
1. all - 所有方向相同
dart
EdgeInsets.all(double value)
用法:
dart
Padding(
padding: EdgeInsets.all(16), // 上下左右都是16
child: Text('All方向填充'),
)
等价于:
dart
EdgeInsets.fromLTRB(16, 16, 16, 16)
2. only - 指定某个方向
dart
EdgeInsets.only({
double left = 0.0,
double top = 0.0,
double right = 0.0,
double bottom = 0.0,
})
用法:
dart
// 只设置左边
Padding(
padding: EdgeInsets.only(left: 8),
child: Text('左侧填充'),
)
// 同时设置多个方向
Padding(
padding: EdgeInsets.only(left: 20, right: 20),
child: Text('左右填充'),
)
3. symmetric - 对称方向
dart
EdgeInsets.symmetric({
double vertical = 0.0, // 上下
double horizontal = 0.0, // 左右
})
用法:
dart
// 只设置上下
Padding(
padding: EdgeInsets.symmetric(vertical: 8),
child: Text('上下填充'),
)
// 同时设置上下和左右
Padding(
padding: EdgeInsets.symmetric(
vertical: 12,
horizontal: 20,
),
child: Text('对称填充'),
)
4. fromLTRB - 四个方向分别指定
dart
EdgeInsets.fromLTRB(
double left,
double top,
double right,
double bottom,
)
用法:
dart
Padding(
padding: EdgeInsets.fromLTRB(20, 10, 20, 30),
child: Text('四个方向不同值'),
)
2.3 方法对比
| 方法 | 参数 | 适用场景 |
|---|---|---|
| all | 1个 | 所有方向相同 |
| only | 1-4个 | 指定某些方向 |
| symmetric | 1-2个 | 对称设置 |
| fromLTRB | 4个 | 四个方向都不同 |
2.4 选择建议
dart
// ✅ 推荐:简洁明了
EdgeInsets.all(16) // 四个方向相同
EdgeInsets.symmetric(horizontal: 16) // 左右相同
EdgeInsets.only(left: 16) // 只设置一个
// ❌ 不推荐:过于繁琐
EdgeInsets.fromLTRB(16, 16, 16, 16) // 应该用all(16)
EdgeInsets.fromLTRB(16, 0, 16, 0) // 应该用symmetric(horizontal: 16)
3️⃣ 详细示例
3.1 all示例
dart
Container(
color: Colors.blue[100],
child: Padding(
padding: EdgeInsets.all(16),
child: Container(
color: Colors.white,
child: Text('16像素填充'),
),
),
)
效果:
┌────────────────────┐
│ ████████████████ │ ← 蓝色背景(外层Container)
│ ██┌──────────┐██ │
│ ██│ 16px填充 │██ │ ← 白色背景(内层Container)
│ ██└──────────┘██ │
│ ████████████████ │
└────────────────────┘
3.2 only示例
dart
Column(
children: [
// 只设置左边
Padding(
padding: EdgeInsets.only(left: 8),
child: Text("Hello world"),
),
// 只设置上下
Padding(
padding: EdgeInsets.only(top: 8, bottom: 8),
child: Text("I am Jack"),
),
// 设置左右
Padding(
padding: EdgeInsets.only(left: 20, right: 20),
child: Text("Your friend"),
),
],
)
3.3 symmetric示例
dart
// 上下填充
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Text('上下各16像素'),
)
// 左右填充
Padding(
padding: EdgeInsets.symmetric(horizontal: 24),
child: Text('左右各24像素'),
)
// 同时设置
Padding(
padding: EdgeInsets.symmetric(
vertical: 12,
horizontal: 20,
),
child: Text('上下12,左右20'),
)
3.4 fromLTRB示例
dart
Padding(
padding: EdgeInsets.fromLTRB(20, 10, 20, 30),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('左:20像素'),
Text('上:10像素'),
Text('右:20像素'),
Text('下:30像素'),
],
),
)
4️⃣ 实际应用场景
场景1:卡片内容填充
dart
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
blurRadius: 4,
offset: Offset(0, 2),
),
],
),
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'文章标题',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
Text(
'文章内容描述...',
style: TextStyle(color: Colors.grey),
),
],
),
),
)
场景2:按钮内边距
dart
Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(4),
),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 24,
vertical: 12,
),
child: Text(
'确定',
style: TextStyle(color: Colors.white),
),
),
)
场景3:列表项间距
dart
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.only(bottom: 8),
child: ListTile(
title: Text('列表项 $index'),
),
);
},
)
场景4:页面整体内边距
dart
Scaffold(
body: Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
// 页面内容
],
),
),
)
🤔 常见问题(FAQ)
Q1: Padding和Margin的区别?
A: 在Flutter中:
| 概念 | 实现方式 | 说明 |
|---|---|---|
| Padding(内边距) | Padding组件 | 子组件内部的留白 |
| Margin(外边距) | Container.margin | 组件外部的留白 |
dart
// Padding(内边距)
Padding(
padding: EdgeInsets.all(16),
child: Container(
color: Colors.blue,
child: Text('Text'),
),
)
// Margin(外边距)
Container(
margin: EdgeInsets.all(16),
color: Colors.blue,
child: Text('Text'),
)
Q2: EdgeInsets.zero是什么?
A: 所有方向填充为0的快捷方式
dart
EdgeInsets.zero // 等价于 EdgeInsets.all(0)
Q3: 如何设置负数填充?
A: Padding不支持负数,但可以用Transform.translate
dart
// ❌ 错误:Padding不支持负数
Padding(
padding: EdgeInsets.all(-10), // 会报错
child: Text('Text'),
)
// ✅ 正确:使用Transform
Transform.translate(
offset: Offset(-10, -10),
child: Text('Text'),
)
Q4: Padding会影响子组件的约束吗?
A: 会!Padding会减小传递给子组件的约束
dart
// 假设父组件约束为 100×100
Container(
width: 100,
height: 100,
child: Padding(
padding: EdgeInsets.all(10),
// 子组件实际可用空间:(100-20)×(100-20) = 80×80
child: Container(color: Colors.blue),
),
)
Q5: 如何选择使用哪个EdgeInsets方法?
A: 遵循简洁原则:
dart
// 四个方向相同 → all
EdgeInsets.all(16)
// 上下或左右相同 → symmetric
EdgeInsets.symmetric(horizontal: 16)
EdgeInsets.symmetric(vertical: 8)
// 只设置1-3个方向 → only
EdgeInsets.only(left: 16)
EdgeInsets.only(left: 16, right: 16)
// 四个方向都不同 → fromLTRB
EdgeInsets.fromLTRB(20, 10, 15, 30)
🎯 跟着做练习
练习1:实现一个带内边距的卡片组件
目标: 创建一个自定义Card组件,内容有16像素填充
步骤:
- 使用Container作为卡片背景
- 添加圆角和阴影
- 使用Padding设置内容填充
💡 查看答案
dart
class CustomCard extends StatelessWidget {
final Widget child;
const CustomCard({super.key, required this.child});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 1,
blurRadius: 4,
offset: Offset(0, 2),
),
],
),
child: Padding(
padding: EdgeInsets.all(16),
child: child,
),
);
}
}
// 使用
CustomCard(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'标题',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
Text('这是卡片的内容描述...'),
],
),
)
练习2:实现响应式Padding
目标: 根据屏幕宽度动态调整Padding值
步骤:
- 使用MediaQuery获取屏幕宽度
- 计算合适的padding值
- 应用动态padding
💡 查看答案
dart
class ResponsivePadding extends StatelessWidget {
final Widget child;
const ResponsivePadding({super.key, required this.child});
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
// 根据屏幕宽度计算padding
double padding;
if (screenWidth < 600) {
padding = 16; // 手机
} else if (screenWidth < 1200) {
padding = 24; // 平板
} else {
padding = 32; // 桌面
}
return Padding(
padding: EdgeInsets.all(padding),
child: child,
);
}
}
// 使用
ResponsivePadding(
child: Text('响应式内容'),
)
📋 小结
核心概念
| 组件/类 | 作用 | 常用方法 |
|---|---|---|
| Padding | 添加填充 | padding属性 |
| EdgeInsets | 设置填充值 | all、only、symmetric、fromLTRB |
EdgeInsets方法速查
dart
EdgeInsets.all(16) // 所有方向16
EdgeInsets.only(left: 8) // 只设置左边
EdgeInsets.only(left: 8, right: 8) // 设置左右
EdgeInsets.symmetric(vertical: 16) // 上下16
EdgeInsets.symmetric(horizontal: 20) // 左右20
EdgeInsets.symmetric( // 上下和左右
vertical: 12,
horizontal: 20,
)
EdgeInsets.fromLTRB(20, 10, 20, 30) // 四个方向分别指定
EdgeInsets.zero // 所有方向为0
记忆技巧
- all:all方向相同
- only:only某些方向
- symmetric:对称的两个方向
- fromLTRB:Left、Top、Right、Bottom顺序