一个全面的 Flutter 自定义动画项目,从基础到高级,涵盖所有动画概念和实战场景
这是一个完整的 Flutter 动画演示项目,包含 62 个精心设计的动画组件 和 5 个综合实战示例,从基础到高级全覆盖。每个组件都配有详细注释、使用示例和性能优化技巧。
- ✅ 67 个动画演示 - 62个独立组件 + 5个综合示例
- ✅ 模块化架构 - 每个组件独立封装可复用
- ✅ 详细注释 - 每个组件包含原理说明和使用示例
- ✅ 性能优化 - AnimatedBuilder、const 优化、性能监控
- ✅ 四大分类 - 基础、中级、高级、交互特效
- ✅ 实战场景 - UI交互、页面转场、加载状态、手势驱动
本项目中的动画根据执行方式分为四种模式:
定义:多个动画同时开始、同时执行,使用单个 AnimationController。
特点:
- 使用同一个 AnimationController
- 创建多个不同的 Animation 对象(如 ScaleTransition、RotationTransition)
- 所有动画同时开始和结束
- 适合创建复合动画效果
示例场景:一个方块同时变大、旋转、变色
// 并行动画示例
final scaleAnimation = Tween<double>(begin: 0.5, end: 1.0).animate(controller);
final rotationAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(controller);
final colorAnimation = ColorTween(begin: Colors.red, end: Colors.blue).animate(controller);
controller.forward(); // 三个动画同时执行定义:多个动画按顺序依次执行,一个完成后再开始下一个。
特点:
- 使用多个 AnimationController
- 通过 addStatusListener 监听动画完成状态
- 一个动画完成后触发下一个
- 适合有明确步骤的动画序列
示例场景:先淡入,停顿,再滑出
// 串行动画示例
controller1.addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller2.forward(); // 第一个完成后启动第二个
}
});
controller1.forward();定义:多个动画按时间间隔依次开始,但并行执行。
特点:
- 使用单个 AnimationController
- 通过 Interval 控制每个动画的开始和结束时间
- 动画之间有时间差,形成波浪效果
- 适合列表项依次出现的场景
示例场景:列表项依次淡入(每隔100ms一个)
// 交错动画示例
final animation1 = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: controller,
curve: Interval(0.0, 0.5), // 前50%时间
),
);
final animation2 = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: controller,
curve: Interval(0.3, 0.8), // 30%-80%时间,与第一个重叠
),
);定义:同一属性的多段变化,或复杂的多阶段动画。
特点:
- 使用 TweenSequence 或多个 Interval
- 一个动画对象包含多个阶段
- 每个阶段可以有不同的目标值和曲线
- 适合复杂的过渡效果
示例场景:先快速放大,停顿,再慢慢缩小
// 链式动画示例(TweenSequence)
final animation = TweenSequence<double>([
TweenSequenceItem(tween: Tween(begin: 0.0, end: 1.5), weight: 40),
TweenSequenceItem(tween: ConstantTween(1.5), weight: 20), // 停顿
TweenSequenceItem(tween: Tween(begin: 1.5, end: 1.0), weight: 40),
]).animate(controller);| 模式 | Controller数量 | 动画关系 | 时间轴 | 典型场景 |
|---|---|---|---|---|
| 并行(Parallel) | 1个 | 同时执行 | 完全重叠 | 复合效果(同时缩放+旋转) |
| 串行(Sequence) | 多个 | 依次执行 | 不重叠 | 分步骤动画(先A后B) |
| 交错(Stagger) | 1个 | 依次开始,并行执行 | 部分重叠 | 列表依次出现 |
| 链式(Chained) | 1个 | 多阶段连续 | 连续变化 | 复杂过渡(先大后小) |
| 组件 | 说明 | 难度 | 执行模式 | 关键技术 |
|---|---|---|---|---|
| 淡入淡出 | 透明度渐变动画 | ⭐ | 单一 | FadeTransition, Tween |
| 缩放动画 | 放大缩小效果 | ⭐ | 单一 | ScaleTransition, Transform.scale |
| 脉冲动画 | 循环缩放效果 | ⭐ | 单一 | repeat(), AnimationController |
| 旋转加载器 | 持续旋转动画 | ⭐ | 单一 | RotationTransition, 弧度转换 |
| 卡片翻转 | 180度3D翻转 | ⭐⭐ | 单一 | Transform, Matrix4 |
| 滑动进入 | 从各方向滑入 | ⭐ | 单一 | SlideTransition, Offset |
| 颜色过渡 | 颜色平滑渐变 | ⭐ | 单一 | ColorTween, Color.lerp |
| 彩虹循环 | 多色循环渐变 | ⭐⭐ | 串行 ⛓️ | ColorTween, addStatusListener |
| 渐变动画 | 动态渐变色 | ⭐⭐ | 单一 | LinearGradient, AnimatedBuilder |
| 交互淡入淡出 | 手动控制动画 | ⭐⭐ | 单一 | forward(), reverse() |
| 交互缩放 | 按钮控制放大缩小 | ⭐⭐ | 单一 | GlobalKey, 状态管理 |
| 交互颜色 | 随机切换颜色 | ⭐⭐ | 单一 | Random, ColorTween |
技术要点:
- AnimationController 的生命周期管理
- Tween 定义起始和结束值
- 使用 dispose() 释放资源防止内存泄漏
- CurvedAnimation 添加缓动效果
- AnimatedBuilder 优化性能
| 组件 | 说明 | 难度 | 执行模式 | 关键技术 |
|---|---|---|---|---|
| 交错列表 | 元素依次出现 | ⭐⭐⭐ | 交错 🎵 | Interval, 单Controller |
| 交错卡片 | 多属性交错动画 | ⭐⭐⭐ | 交错 🎵 + 并行 🔀 | 淡入+缩放+滑动组合 |
| 柱状图动画 | 弹性曲线效果 | ⭐⭐⭐ | 交错 🎵 | Curves.elasticOut |
| 简单序列 | 动画顺序播放 | ⭐⭐⭐ | 串行 ⛓️ | addStatusListener, 链式调用 |
| 多元素序列 | 多个元素依次执行 | ⭐⭐⭐ | 串行 ⛓️ | 状态监听, 顺序控制 |
| 链式变换 | 复杂多阶段动画 | ⭐⭐⭐⭐ | 链式 🔗 | Interval组合, TweenSequence |
| Hero共享元素 | 页面转场动画 | ⭐⭐ | 单一 | Hero, MaterialPageRoute |
| Hero网格 | 多个Hero演示 | ⭐⭐⭐ | 单一 | 多Hero, GridView |
| 动画列表 | 列表项动态增删 | ⭐⭐⭐ | 交错 🎵 | AnimatedList, GlobalKey |
| 形状变换 | CustomPainter绘制 | ⭐⭐⭐⭐ | 单一 | CustomPainter, Path插值 |
| 圆形到方形 | 简单形状变换 | ⭐⭐⭐ | 单一 | BorderRadius, 动画插值 |
技术要点:
- Interval 实现时间轴控制
- addStatusListener 监听动画状态
- Hero 共享元素的 tag 匹配
- AnimatedList 的 insertItem 和 removeItem
- CustomPainter 结合动画创建复杂图形
| 组件 | 说明 | 难度 | 执行模式 | 关键技术 |
|---|---|---|---|---|
| 弹簧弹跳 | SpringSimulation效果 | ⭐⭐⭐⭐ | 单一 | mass, stiffness, damping |
| 可拖拽弹簧 | 拖动回弹效果 | ⭐⭐⭐⭐ | 单一 | GestureDetector, 弹簧物理 |
| 自定义弹簧 | 实时调节参数 | ⭐⭐⭐⭐ | 单一 | Slider, 交互式调节 |
| 摩擦滚动 | FrictionSimulation | ⭐⭐⭐⭐ | 单一 | drag, velocity |
| 投掷球 | 水平投掷减速 | ⭐⭐⭐⭐ | 单一 | 摩擦系数, 速度衰减 |
| 自定义摩擦 | 火箭上升减速 | ⭐⭐⭐⭐ | 并行 🔀 | 旋转, 重力效果 |
| 组件 | 说明 | 难度 | 执行模式 | 关键技术 |
|---|---|---|---|---|
| 简单波浪 | 正弦函数波浪 | ⭐⭐⭐ | 单一 | sin, CustomPainter, Path |
| 多层波浪 | 3层叠加效果 | ⭐⭐⭐⭐ | 并行 🔀 | 多层绘制, 不同速度 |
| 交互式波浪 | 调节频率振幅 | ⭐⭐⭐⭐ | 单一 | 实时参数调节 |
| 圆形扩散 | 同心圆扩散 | ⭐⭐⭐⭐ | 交错 🎵 | 圆形绘制, 透明度 |
| 加载波浪 | 水位上升效果 | ⭐⭐⭐⭐ | 并行 🔀 | 百分比显示, 加载动画 |
| 组件 | 说明 | 难度 | 执行模式 | 关键技术 |
|---|---|---|---|---|
| 爆炸粒子 | 点击触发爆炸 | ⭐⭐⭐⭐⭐ | 并行 🔀 | 粒子系统, 重力, 径向发射 |
| 飘雪效果 | 持续生成雪花 | ⭐⭐⭐⭐ | 并行 🔀 | 连续生成, 水平摆动 |
| 烟花效果 | 绚丽烟花动画 | ⭐⭐⭐⭐⭐ | 串行 ⛓️ + 并行 🔀 | 圆形爆炸, 多色, 重力 |
| 彩纸庆祝 | 按钮触发彩纸 | ⭐⭐⭐⭐⭐ | 并行 🔀 | 矩形粒子, 旋转, 重力 |
| 组件 | 说明 | 难度 | 执行模式 | 关键技术 |
|---|---|---|---|---|
| 液态滑动 | 手势驱动切换 | ⭐⭐⭐⭐⭐ | 单一 | CustomClipper, Bezier, 手势 |
| 简单液态 | 自动往返效果 | ⭐⭐⭐⭐ | 单一 | 自动动画, 双页切换 |
| 交互式液态 | 调节进度和强度 | ⭐⭐⭐⭐ | 单一 | Slider, 实时调节 |
| 波浪揭示 | 显示/隐藏内容 | ⭐⭐⭐⭐ | 单一 | 按钮触发, 状态切换 |
| 组件 | 说明 | 难度 | 执行模式 | 关键技术 |
|---|---|---|---|---|
| 弹性按钮 | 点击弹性反馈 | ⭐⭐⭐ | 单一 | Curves.elasticOut, 按钮交互 |
| 弹性菜单 | 菜单项弹性展开 | ⭐⭐⭐⭐ | 交错 🎵 | Staggered, Interval |
| 弹性图标 | 图标依次弹出 | ⭐⭐⭐ | 交错 🎵 | 交错出现, 统一触发 |
| 自定义弹性曲线 | 切换不同曲线 | ⭐⭐⭐ | 单一 | elasticIn/Out/InOut |
| 弹性拖拽 | 拖动弹性回弹 | ⭐⭐⭐⭐ | 单一 | 拖拽手势, 弹性物理 |
技术要点:
- SpringSimulation 和 FrictionSimulation 物理引擎
- CustomPainter 的 Canvas API 使用
- 粒子系统的生命周期管理
- CustomClipper 和贝塞尔曲线
- 弹性曲线提升交互体验
- RepaintBoundary 性能优化
| 组件 | 说明 | 难度 | 执行模式 | 关键技术 |
|---|---|---|---|---|
| 简单滑动删除 | Dismissible组件 | ⭐⭐ | 单一 | Dismissible, onDismissed |
| 自定义滑动删除 | 双向操作 | ⭐⭐⭐ | 单一 | confirmDismiss, 双向滑动 |
| 手动控制滑动 | 自定义拖动逻辑 | ⭐⭐⭐⭐ | 单一 | GestureDetector, 阈值触发 |
| 简单交互查看器 | 缩放平移 | ⭐⭐ | 并行 🔀 | InteractiveViewer, minScale, maxScale |
| 图片缩放查看器 | 带控制按钮 | ⭐⭐⭐ | 并行 🔀 | TransformationController |
| 自定义平移缩放 | 手动处理手势 | ⭐⭐⭐⭐ | 并行 🔀 | onScaleUpdate, 手势详情 |
| 双击缩放 | 双击切换状态 | ⭐⭐ | 单一 | onDoubleTap, 动画过渡 |
| 组件 | 说明 | 难度 | 执行模式 | 关键技术 |
|---|---|---|---|---|
| 简单涟漪 | 点击涟漪扩散 | ⭐⭐⭐ | 单一 | CustomPainter, 圆形扩散 |
| 多重涟漪 | 多层依次扩散 | ⭐⭐⭐ | 交错 🎵 | 多层动画, 延迟效果 |
| 连续涟漪 | 雷达扫描效果 | ⭐⭐⭐ | 交错 🎵 | 循环动画, 透明度渐变 |
| Ink涟漪 | Material风格 | ⭐⭐ | 单一 | InkWell, Material |
| 简单闪光 | 骨架屏加载 | ⭐⭐⭐ | 单一 | Shimmer, LinearGradient |
| 闪光列表 | 列表骨架屏 | ⭐⭐⭐ | 单一 | ListView, ShaderMask |
| 闪光卡片 | 复杂布局加载 | ⭐⭐⭐ | 单一 | 自定义颜色, 复杂布局 |
| 加载状态切换 | 加载和内容切换 | ⭐⭐⭐ | 单一 | AnimatedSwitcher, 状态管理 |
技术要点:
- Dismissible 快速实现滑动删除
- InteractiveViewer 内置缩放平移
- GestureDetector 底层手势检测
- CustomPainter + 动画创建视觉效果
- ShaderMask 实现 Shimmer 效果
- 骨架屏提升感知性能
| 示例 | 说明 | 难度 | 执行模式 | 涉及技术 |
|---|---|---|---|---|
| 浮动菜单 | 圆形排列展开菜单 | ⭐⭐⭐⭐ | 交错 🎵 + 并行 🔀 | Staggered + Elastic + 圆形布局 |
| 底部导航 | 动画底部导航栏 | ⭐⭐⭐ | 并行 🔀 | Scale + TextStyle + 状态切换 |
| 侧边抽屉 | 交错侧边菜单 | ⭐⭐⭐⭐ | 交错 🎵 | Slide + Staggered + Transform |
| 应用引导页 | PageView滑动引导 | ⭐⭐⭐⭐ | 并行 🔀 + 链式 🔗 | PageView + Scale + Indicator |
| 步骤引导 | 线性步骤指示器 | ⭐⭐⭐ | 串行 ⛓️ | Stepper + AnimatedContainer |
lib/
├── main.dart # 应用入口,主题配置
├── core/ # 核心工具模块
│ ├── constants/ # 常量定义
│ │ ├── animation_constants.dart # 动画相关常量(时长、曲线)
│ │ └── app_colors.dart # 应用配色方案
│ ├── utils/ # 工具函数
│ │ └── animation_utils.dart # 动画辅助函数
│ └── widgets/ # 通用组件
│ └── demo_card.dart # 演示卡片组件
│
├── screens/ # 展示页面
│ ├── home_screen.dart # 主页(导航入口)
│ ├── basic_animations_screen.dart # 基础动画页面
│ ├── intermediate_screen.dart # 中级动画页面
│ ├── advanced_screen.dart # 高级动画页面
│ ├── gestures_effects_screen.dart # 手势交互&特效页面
│ └── examples_screen.dart # 综合示例页面
│
└── animations/ # 动画组件库
├── basic/ # 基础动画(12个)
│ ├── fade_animation.dart # 淡入淡出动画
│ ├── scale_animation.dart # 缩放动画
│ ├── rotation_animation.dart # 旋转动画
│ ├── slide_animation.dart # 滑动动画
│ └── color_tween_animation.dart # 颜色渐变动画
│
├── intermediate/ # 中级动画(11个)
│ ├── staggered_animation.dart # 交错动画
│ ├── sequence_animation.dart # 序列动画
│ ├── hero_animation.dart # Hero共享元素动画
│ ├── animated_list_demo.dart # 列表动画
│ └── morphing_shapes.dart # 形状变换动画
│
├── advanced/ # 高级动画(24个)
│ ├── physics_spring.dart # 弹簧物理动画
│ ├── physics_friction.dart # 摩擦物理动画
│ ├── custom_painter_wave.dart # 波浪动画
│ ├── particle_system.dart # 粒子系统
│ ├── liquid_swipe.dart # 液态滑动
│ └── elastic_animation.dart # 弹性动画
│
├── gestures/ # 手势交互(7个)
│ ├── swipe_to_delete.dart # 滑动删除
│ └── interactive_viewer.dart # 交互式查看器
│
├── ui_effects/ # UI特效(8个)
│ ├── ripple_effect.dart # 涟漪效果
│ └── shimmer_loading.dart # 闪光加载
│
└── examples/ # 综合示例(5个)
├── animated_menu.dart # 动画菜单
└── onboarding_page.dart # 引导页面
- constants/: 项目常量
animation_constants.dart: 动画时长、曲线等常量app_colors.dart: 统一的配色方案
- utils/: 工具函数
animation_utils.dart: 动画相关辅助函数
- widgets/: 通用组件
demo_card.dart: 统一的演示卡片样式
各个分类的导航页面,展示对应分类的所有动画组件。
- basic/: 基础动画,适合初学者
- intermediate/: 中级动画,需要一定基础
- advanced/: 高级动画,涉及复杂技术
- gestures/: 手势驱动的交互动画
- ui_effects/: 视觉特效动画
- examples/: 实战综合示例
- Flutter SDK: >= 3.0.0
- Dart SDK: >= 3.0.0
# 进入项目目录
cd animations_demo
# 安装依赖
flutter pub get# 运行到连接的设备
flutter run
# 运行到特定设备
flutter run -d <device_id>
# 运行 Web 版本
flutter run -d chrome# 构建 Android APK
flutter build apk
# 构建 iOS
flutter build ios
# 构建 Web
flutter build webimport 'package:animations_demo/animations/basic/fade_animation.dart';
class MyPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FadeInDemo(), // 使用淡入淡出动画
),
);
}
}class MyAnimation extends StatefulWidget {
@override
_MyAnimationState createState() => _MyAnimationState();
}
class _MyAnimationState extends State<MyAnimation>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
// 创建控制器
_controller = AnimationController(
duration: const Duration(milliseconds: 500),
vsync: this,
);
// 创建补间动画
_animation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
);
// 启动动画
_controller.forward();
}
@override
void dispose() {
_controller.dispose(); // 释放资源
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Opacity(
opacity: _animation.value,
child: child,
);
},
child: const Text('Hello Animation!'),
);
}
}// 创建多个动画,使用 Interval 控制时间
final opacityAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: controller,
curve: const Interval(0.0, 0.5, curve: Curves.easeIn), // 前50%时间
),
);
final scaleAnimation = Tween<double>(begin: 0.5, end: 1.0).animate(
CurvedAnimation(
parent: controller,
curve: const Interval(0.5, 1.0, curve: Curves.easeOut), // 后50%时间
),
);import 'package:flutter/physics.dart';
// 弹簧模拟
final spring = SpringSimulation(
SpringDescription(
mass: 1,
stiffness: 100,
damping: 10,
),
0.0, // 起始位置
1.0, // 结束位置
0.0, // 初始速度
);
_controller.animateWith(spring);
// 摩擦模拟
final friction = FrictionSimulation(
0.1, // 拖拽系数
0.0, // 起始位置
100.0, // 初始速度
);
_controller.animateWith(friction);// 好的做法
const Text('Hello')
// 避免
Text('Hello')AnimatedBuilder(
animation: animation,
builder: (context, child) {
return Transform.scale(
scale: animation.value,
child: child, // 不会重建
);
},
child: const ExpensiveWidget(), // 只构建一次
)RepaintBoundary(
child: AnimatedWidget(...), // 隔离重绘区域
)// 避免
builder: (context, child) {
final result = expensiveCalculation(); // 每帧都执行
return Widget(...);
}
// 推荐
final result = expensiveCalculation(); // 提前计算
builder: (context, child) {
return Widget(...);
}AnimationController(
duration: const Duration(milliseconds: 300), // 合理的时长
vsync: this,
);// AnimatedWidget 自动订阅动画,无需手动调用 setState
class FadeContainer extends AnimatedWidget {
const FadeContainer({Key? key, required Animation<double> animation})
: super(key: key, listenable: animation);
@override
Widget build(BuildContext context) {
final animation = listenable as Animation<double>;
return Opacity(
opacity: animation.value,
child: Container(...),
);
}
}动画的核心控制器,管理动画的生命周期。
final controller = AnimationController(
duration: const Duration(seconds: 1),
vsync: this, // 需要 TickerProviderStateMixin
);
// 播放动画
controller.forward();
// 反向播放
controller.reverse();
// 循环播放
controller.repeat();
// 停止动画
controller.stop();
// 重置动画
controller.reset();
// 跳转到指定值
controller.animateTo(0.5);定义动画的起始值和结束值。
// 数值补间
Tween<double>(begin: 0.0, end: 100.0)
// 颜色补间
ColorTween(begin: Colors.red, end: Colors.blue)
// 偏移补间
Tween<Offset>(begin: Offset.zero, end: Offset(1.0, 0.0))
// 尺寸补间
Tween<Size>(begin: Size(50, 50), end: Size(100, 100))为动画添加缓动曲线。
final curvedAnimation = CurvedAnimation(
parent: controller,
curve: Curves.easeInOut, // 缓入缓出
);基础曲线:
Curves.linear: 线性Curves.easeIn: 缓入Curves.easeOut: 缓出Curves.easeInOut: 缓入缓出
弹跳曲线:
Curves.bounceIn: 弹跳进入Curves.bounceOut: 弹跳退出Curves.bounceInOut: 弹跳进入和退出
弹性曲线:
Curves.elasticIn: 弹性进入Curves.elasticOut: 弹性退出Curves.elasticInOut: 弹性进入和退出
其他曲线:
Curves.decelerate: 减速Curves.fastOutSlowIn: 快出慢入Curves.slowMiddle: 中间慢
// 弹簧模拟
SpringSimulation(
SpringDescription(
mass: 1, // 质量
stiffness: 100, // 刚度
damping: 10, // 阻尼
),
0.0, // 起始位置
1.0, // 结束位置
0.0, // 初始速度
);
// 摩擦模拟
FrictionSimulation(
0.1, // 拖拽系数
0.0, // 起始位置
100.0, // 初始速度
);
// 重力模拟
GravitySimulation(
9.8, // 加速度
0.0, // 起始位置
1.0, // 结束位置
0.0, // 初始速度
);- Hero 共享元素动画
- 路由转场动画
- 页面切换效果
- 模态弹窗动画
- 滑动删除
- 下拉刷新
- 列表项动画
- 展开/收起动画
- Shimmer 骨架屏
- 加载指示器
- 进度条动画
- 占位符动画
- 按钮点击反馈
- 涟漪效果
- 弹性动画
- 震动反馈
- 图表动画
- 进度动画
- 粒子效果
- 波浪效果
- 拖拽排序
- 缩放查看
- 滑动切换
- 长按展开
本项目采用 MIT 许可证 - 详见 LICENSE 文件
最后更新: 2025-11-25 | 版本: v1.0.0