4. 使用Container与BoxDecoration绘制卡片UI
卡片视觉的四个可调层
Container 本身只是“布局容器”,真正决定卡片外观的是 BoxDecoration。把一张卡片拆开看,它由四层叠加而成:最外层是 margin(卡片与周围内容的间距),然后是 decoration 的阴影(boxShadow),再是渐变背景(gradient)与圆角(borderRadius),最内层是 padding(内容与卡片边缘的距离)。理解这四层的叠加顺序,就能独立调节每一层而不互相干扰。
完整可运行示例
下面这个卡片组件把四层参数都显式写出来,方便逐项调整观察效果。外层用 margin 控制卡片间距,decoration 负责圆角、阴影和渐变,padding 控制文字与边缘的距离。
import 'package:flutter/material.dart';
void main() => runApp(const MaterialApp(home: CardDemoPage()));
class CardDemoPage extends StatelessWidget {
const CardDemoPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF7F9FC),
body: Center(
child: Container(
// ① 外层间距:卡片与周围内容的距离
margin: const EdgeInsets.all(24),
// ④ 内边距:内容与卡片边缘的距离
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 18),
// ②③ 装饰:阴影 + 渐变 + 圆角
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xFF5B8DEF), Color(0xFF8E6BF0)],
),
borderRadius: BorderRadius.circular(20),
boxShadow: const [
BoxShadow(
color: Color(0x473A4A6B),
blurRadius: 12,
offset: Offset(0, 6),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
'Flutter 实战',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
Text(
'Container + BoxDecoration 卡片',
style: TextStyle(color: Color(0xFFEAF0FF), fontSize: 13),
),
],
),
),
),
);
}
}
参数调节与效果对照
改一个参数就能看出它控制哪一层。下表给出常用取值与视觉变化,便于按需微调。
| 参数 | 示例值 | 视觉变化 |
|---|---|---|
| margin | EdgeInsets.all(24) | 卡片四周留白增大,与屏幕边缘距离变远 |
| padding | EdgeInsets.symmetric(h:20, v:18) | 文字与卡片边缘间距增大,卡片显得更“透气” |
| borderRadius | BorderRadius.circular(20) | 圆角变大,卡片更柔和;设为 0 则为直角 |
| boxShadow.blurRadius | 12 | 数值越大阴影越弥散,越小越锐利 |
| boxShadow.offset | Offset(0, 6) | 正值向下偏移,形成“悬浮”感 |
| gradient.colors | [#5B8DEF, #8E6BF0] | 改变渐变两端颜色,决定卡片主色调 |
若卡片需要描边,在 BoxDecoration 中加 border: Border.all(color: Colors.white24, width: 1)。圆角会同时裁剪背景、边框和阴影,无需额外处理。
color 与 gradient 同时设置时,gradient 会覆盖 color,容易造成“改了颜色没反应”的困惑。二者只保留一个即可。
验证要点
- 卡片四角为圆角,且阴影沿圆角轮廓分布,不出现直角阴影。
- 背景为左上到右下的蓝紫渐变,文字为白色且与背景对比清晰。
- 调整 margin 时卡片整体位置变化,调整 padding 时仅内部文字位置变化,二者互不影响。
- 把 boxShadow 的 blurRadius 改为 0,阴影消失,可确认阴影确实来自该参数。