"优秀的动画应该像呼吸一样自然——用户几乎不会注意到它的存在,但缺少时会明显感到不适。"
一、Flutter动画核心概念
1. 动画系统三要素
要素 | 说明 | 对应类 |
---|---|---|
控制器 | 管理动画进度 | AnimationController |
插值器 | 定义值变化规律 | Tween |
曲线 | 控制变化速率 | Curve |
2. 动画类型对比
类型 | 特点 | 适用场景 |
---|---|---|
隐式动画 | 自动过渡 | 简单属性变化 |
显式动画 | 精细控制 | 复杂动画序列 |
物理动画 | 真实运动 | 交互反馈 |
二、基础动画实现
1. 隐式动画示例
AnimatedContainer( duration: Duration(seconds: 1), width: _expanded ? 200 : 100, height: _expanded ? 200 : 100, color: _expanded ? Colors.red : Colors.blue, curve: Curves.easeInOut, )
2. 显式动画完整流程
class RotationDemo extends StatefulWidget { @override _RotationDemoState createState() => _RotationDemoState(); } class _RotationDemoState extends State<RotationDemo> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _animation; @override void initState() { super.initState(); _controller = AnimationController( duration: Duration(seconds: 2), vsync: this, ); _animation = Tween(begin: 0.0, end: 2 * pi).animate(_controller) ..addListener(() => setState(() {})); _controller.repeat(); } @override Widget build(BuildContext context) { return Transform.rotate( angle: _animation.value, child: FlutterLogo(size: 100), ); } @override void dispose() { _controller.dispose(); super.dispose(); } }
三、高级动画技巧
1. 交错动画(Staggered Animation)
AnimationController( duration: Duration(seconds: 2), vsync: this, ); Animation<double> opacity = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation( parent: _controller, curve: Interval(0.0, 0.5), ); Animation<Offset> slide = Tween<Offset>( begin: Offset(0, 1), end: Offset.zero, ).animate( CurvedAnimation( parent: _controller, curve: Interval(0.5, 1.0), );
2. 基于物理的动画
dart
final spring = SpringSimulation( SpringDescription( mass: 1, stiffness: 100, damping: 10, ), 0, // 起始位置 1, // 结束位置 10, // 初始速度 ); _controller.animateWith(spring);
四、性能优化指南
1. 重建范围控制
// ❌ 低效做法 @override Widget build(BuildContext context) { return Transform.rotate( angle: _animation.value, child: HeavyWidget(), ); } // ✅ 高效做法 AnimatedBuilder( animation: _animation, builder: (_, child) => Transform.rotate( angle: _animation.value, child: child, ), child: HeavyWidget(), // 不会重建 );
2. 动画性能黄金法则
指标 | 标准值 | 检测工具 |
---|---|---|
FPS | ≥60 | Performance Overlay |
帧耗时 | <16ms | DevTools |
内存占用 | <50MB | Memory Profiler |
五、实战案例:购物车动画
1. 抛物线动画实现
// 使用Tween组合实现抛物线 Animation<Offset> _getParabolaAnimation(Offset start, Offset end) { final midX = (start.dx + end.dx) / 2; final midY = start.dy - 100; return TweenSequence([ TweenSequenceItem( tween: Tween(begin: start, end: Offset(midX, midY)), weight: 0.5, ), TweenSequenceItem( tween: Tween(begin: Offset(midX, midY), end: end), weight: 0.5, ), ]).animate(_controller); }
2. 动画状态管理
// 使用AnimationStatus监听状态 _controller.addStatusListener((status) { if (status == AnimationStatus.completed) { _showAddToCartSuccess(); } });
六、常见问题解决
1. 动画卡顿排查流程
检查Performance Overlay的UI线程
确认没有在动画回调中执行耗时操作
验证图片资源是否已预加载
2. 动画不执行原因
忘记调用
_controller.forward()
没有正确保持
AnimationController
引用TickerProvider
未正确混入
七、总结与资源
动画设计原则
一致性:保持相同类型的动画参数统一
目的性:每个动画都应增强用户体验
适度性:避免过度使用动画
推荐资源:
Flutter官方动画教程
Rive动画设计工具
Lottie动画库集成