1.在Flutter中动画分为两类:基于tween或基于物理的。
- 补间动画(Tween):在补间动画中,定义了开始点和结束点、时间线以及定义转换时间和速度的曲线。然后由框架计算如何从开始点过渡到结束点;
- 基于物理的动画:在基于物理的动画中,运动被模拟为与真实世界的行为相似。
2.Flutter中动画常用的API
- Animation:是Flutter动画库中的一个核心类,它生成指导动画的值;
- AnimationController:Animation的一个子类,用来管理Animation;
- Tween :在正在执行动画的对象所使用的数据范围之间生成值。例如,Tween可生成从红到蓝之间的色值;
- AnimatedBuilder:是拆分动画的一个工具类,可以将动画和Widget进行分离,而AnimatedWidget理解为Animation的帮助类;
- AnimatedBuilder与AnimatedWidget的最大区别在于对动画拆分上AnimatedBuilder的模式可以将动画逻辑与widget展示进行拆分,而AnimatedWidget是融合在一起的。
(1)Animation
在Flutter中,Animation对象本身和UI渲染没有关系,它是一个抽象类,拥有当前值和状态。并且有一个泛型,常用的是Animation<double>
。
Flutter中Animation对象是一个在一段时间内依次生成一个区间之间值的类输出的值可以是线性的、曲线的或者一个任意函数。根据Animation对象的控制方式,动画可以反向运行,甚至可以在中间切换方向。
- Animation还可以生成其他类型的值,如:
Animation<Color>
、Animation<Size>
等; - Animation对象有状态。可以通过其value属性获取动画的当前值;
- Animation对象本身和UI渲染没有任何关系;
(2)AnimationController
AnimationController
是一个特殊的Animation
对象,在屏幕刷新的每一帧,就会生成一个新的值。默认情况下,AnimationController
在给定的时间段会线性的生成0.0到1.0的数字。例如:
final AnimationController controller = new AnimationController(duration:const Duration(milliseconds:2000),vsync:this);
AnimationController
派生自Animation<double>
,因此可以再需要Animation对象的任何地方使用。但是,AnimationController
常用方法:
forward()
:启动动画;reverse()
:倒放动画;reset()
:重置动画,将其设置到动画的开始位置;stop()
:停止动画;
创建AnimationController时,需要传一个vsync参数,存在vsync时会防止屏幕外动画消耗不必要的资源,可以将stateful对象作为vsync的值。
(3)Tween
默认情况下,AnimationController对象的范围从0.0到1.0.如果需要不同范围,可以设置:
final Tween tween = Tween<double>(begin: 0.0, end: 100.0);
Tween继承了Animatable<T>
。Animatable与Animation相似,不是必须输出double值。例如,ColorTween可以指定两种颜色之间的过渡。
final Tween colorTween = ColorTween(begin: Colors.red, end: Colors.blue);
Tween对象不存储任何状态。它提供了evaluate(Animation<double> animation)
方法将映射函数应用于动画当前值。Animation对象的当前值可以通过value()
获取。evaluate方法还执行了一些其他处理,例如分别确保在动画值为0.0和1.0时返回开始和结束状态。
Tween.animate
要使用Tween对象,可调用它的animate()方法,传入一个控制器。例如:
final AnimationController controller = AnimationController(
vsync: this, duration: const Duration(milliseconds: 500));
Animation<int> tween = IntTween(begin: 0, end: 255).animate(controller);
animate()
返回一个Animation.
结合CurvedAnimation使用:
final AnimationController controller = AnimationController(
vsync: this, duration: const Duration(milliseconds: 500));
final Animation<double> curve =
CurvedAnimation(parent: controller, curve: Curves.easeOut);
Animation<int> tween = IntTween(begin: 0, end: 255).animate(curve);
3.动画添加监听器
如果需要知道动画执行的进度和状态,可以通过Animation的addListener
和addStatusListener
方法给动画添加监听器:
- addListener:动画的值发生变化时会被调用;
- addStatusListener:动画的状态发生变化时会被调用;
4.实现一个从小到大的动画
class LogoAnimation extends StatefulWidget {
const LogoAnimation({Key? key}) : super(key: key);
State<LogoAnimation> createState() => _LogoAnimationState();
}
class _LogoAnimationState extends State<LogoAnimation>
with SingleTickerProviderStateMixin {
Animation<double>? animation;
AnimationController? controller;
void initState() {
super.initState();
controller =
AnimationController(vsync: this, duration: const Duration(seconds: 2));
animation = Tween(begin: 0.0, end: 200.0).animate(controller!)
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller!.reverse();
} else if (status == AnimationStatus.dismissed) {
controller!.forward();
}
})
..addListener(() {
setState(() {});
});
controller!.forward();
}
void dispose() {
controller?.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('动画'),
),
body: Center(
child: Container(
height: animation?.value,
width: animation?.value,
child: const FlutterLogo(),
),
),
);
}
}
5.用AnimatedWidget与AnimatedBuilder
AnimatedWidget
可以将AnimatedWidget理解为Animation的助手,使用它可以简化对动画的使用,在不使用AnimatedWidget的情况下需要手动调用动画的addListener()并在回调中添加setState才能看到动画的效果,AnimatedWidget简化了这一操作。
AnimatedBuilder
AnimatedBuilder是用于构建动画的通用widget,AnimatedBuilder对于希望将动画作为更大构建函数的一部分包含在内的更复杂的widget时,非常适用。其实AnimatedBuilder是拆分动画的一个工具类,适用它可以将动画和widget进行解耦分离。