一、动画基础:从零开始理解Flutter动画
在Flutter中,动画的核心是Animation和AnimationController。我们先从一个最简单的透明度动画开始:
import 'package:flutter/material.dart';
class FadeInDemo extends StatefulWidget {
@override
_FadeInDemoState createState() => _FadeInDemoState();
}
class _FadeInDemoState extends State<FadeInDemo> with SingleTickerProviderStateMixin {
late AnimationController _controller; // 控制动画的启动、停止和进度
late Animation<double> _animation; // 定义动画的值范围
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2), // 动画持续2秒
vsync: this, // 绑定到当前Widget
);
_animation = Tween(begin: 0.0, end: 1.0).animate(_controller); // 透明度从0到1
_controller.forward(); // 启动动画
}
@override
Widget build(BuildContext context) {
return FadeTransition(
opacity: _animation,
child: Container(
width: 200,
height: 200,
color: Colors.blue,
),
);
}
@override
void dispose() {
_controller.dispose(); // 释放资源
super.dispose();
}
}
注释说明:
Tween定义了动画的起始值和结束值。vsync参数用于防止动画在后台运行时消耗资源。
二、进阶技巧:组合动画与物理效果
Flutter的CurvedAnimation可以让动画更自然。比如实现一个弹跳效果:
class BounceDemo extends StatefulWidget {
@override
_BounceDemoState createState() => _BounceDemoState();
}
class _BounceDemoState extends State<BounceDemo> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
_animation = CurvedAnimation(
parent: _controller,
curve: Curves.bounceOut, // 使用预置的弹跳曲线
)..addListener(() => setState(() {})); // 强制重绘
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Transform.scale(
scale: _animation.value, // 缩放比例随动画值变化
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
);
}
}
关联技术:Curves类提供了多种预设动画曲线,如easeIn、elasticOut等。
三、交互式动画:手势与动画结合
通过手势控制动画进度,比如拖动滑块改变动画位置:
class DragAnimationDemo extends StatefulWidget {
@override
_DragAnimationDemoState createState() => _DragAnimationDemoState();
}
class _DragAnimationDemoState extends State<DragAnimationDemo> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<Offset> _animation;
double _dragProgress = 0.0; // 记录拖动进度
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 1),
vsync: this,
);
_animation = Tween<Offset>(
begin: Offset.zero,
end: const Offset(1.5, 0.0), // 水平移动1.5倍宽度
).animate(_controller);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onHorizontalDragUpdate: (details) {
setState(() {
_dragProgress = (_dragProgress + details.primaryDelta! / 300).clamp(0.0, 1.0);
_controller.value = _dragProgress; // 同步动画进度
});
},
child: SlideTransition(
position: _animation,
child: Container(
width: 100,
height: 100,
color: Colors.green,
),
),
);
}
}
注意事项:
- 手势数据需要归一化到
[0,1]范围。 - 实际项目中建议使用
GestureDetector的onPanUpdate更精确。
四、复杂场景:Hero动画与路由切换
Hero动画用于页面间共享元素的过渡效果:
// 页面1
class Page1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => Page2())),
child: Hero(
tag: 'sharedElement', // 唯一标识
child: Container(
width: 100,
height: 100,
color: Colors.purple,
),
),
);
}
}
// 页面2
class Page2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Hero(
tag: 'sharedElement',
child: Container(
width: 200,
height: 200, // 尺寸变化会自动过渡
color: Colors.purple,
),
);
}
}
技术优缺点:
- 优点:无需手动管理动画,代码简洁。
- 缺点:仅适用于全屏路由切换场景。
应用场景与技术总结
典型场景:
- 加载状态提示(旋转/淡入)
- 用户引导(高亮聚焦)
- 游戏交互(物理引擎)
注意事项:
- 避免过度使用动画导致性能问题。
- 使用
AnimatedBuilder优化性能,避免不必要的重绘。
总结:Flutter动画体系灵活强大,从基础到复杂交互均可覆盖。掌握核心类(Animation、Tween、Curves)和设计模式(如AnimatedWidget),能显著提升用户体验。
评论