Flutter动画
基本的动画概念和类
关键点
- Animation是Flutter动画库中的核心类, 插入用于引导动画的值.
- Animation知道当前动画的状态(比如, 是否开始, 暂停, 或继续或反转), 但是不关心屏幕显示的是什么.
- AnimationController用于管理动画.
- CurvedAnimation定义过程为非线性曲线.
- Tween 定义了动画变化的区间. 比如从红色到蓝色, 或从0到255.
- 使用Listeners和StatusListeners监听动画的状态改变.
Flutter中的动画系统基于Animation对象. 控件可以通过读取它们的当前值并监听它们的状态变化,直接将这些动画合并到它们的构建函数中,或者它们可以将动画作为更复杂的动画的基础,并将它们传递给其它控件。
Animation<double>
在Flutter中, 动画对象不关心屏幕显示的是什么. Animation是一个抽象类, 它知道当前的值和状态(完成或取消). 其中被广泛使用的动画类型是Animation<double>.
Animation在Flutter中是一个定义了在特定时间内2个值区间内变化的类. Animation的输出可能是线性, 也可能是曲线. 一个步骤函数, 或者任何其它你可以设计的映射. 根据动画对象的控制方式, 它可以反向运行,甚至可以在中间切换方向。
Animation也可以插入除double以外的类型, 比如Animation<Color>或Animation<Size>.
Animation
拥有状态. 它当前的值可以通过成员.value
获取.
Animation对象不关心 rendering或build()
方法.
CurvedAnimation
CurvedAnimation定义过程为非线性曲线.
final CurvedAnimation curve =
CurvedAnimation(parent: controller, curve: Curves.easeIn);
备注: Curves定义了很多通用曲线. 当然你也可以自己定义, 比如:
class ShakeCurve extends Curve {
@override
double transform(double t) {
return math.sin(t * math.PI * 2);
}
}
CurvedAnimation和AnimationController都是Animation<double>, 因此你可以把它们互相转换. CurvedAnimation包装了它正在修改的对象 - 你不需要子类化AnimationController来实现一条曲线.
AnimationController
AnimationController是一个特殊的动画对象, 每当硬件为一个新框架准备好时, 它就会产生一个新的值. 在默认情况下, 一个AnimationController在给定的时间内线性地产生0到1.0的数字。例如,这段代码创建一个动画对象, 但不启动它:
final AnimationController controller = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
AnimationController继承自Animation<double>, 所以它可以在任何需要动画对象的地方使用。然而,AnimationController有额外的方法来控制动画. 例如,你可以使用.forward()方法启动一个动画. 数字的生成与屏幕刷新绑定在一起,所以通常每秒生成60个数字. 在生成每个数字之后, 每个动画对象都会调用附着的侦听器对象. 要为每个孩子创建一个自定义显示列表, 请参阅 RepaintBoundary.
在创建AnimationController时, 您可以传递一个vsync参数. vsync的存在阻止了屏幕动画使用不必要的资源. 您可以通过在类定义中加入单点的SingleTickerProviderStateMixin来使用有状态对象作为vsync. 你可以在GitHub上看到一个这样的例子animate1.
注意: 在某些情况下, 一个位置可能会超过AnimationController的0.0-1.0范围。例如, fling()函数允许您提供速度, 力和位置(通过Force对象). 这个位置可以是任何东西, 所以可以在0到1.0范围之外。
一个曲率动画也可以超过0到1.0的范围, 即使动画控制器没有. 根据所选择的曲线, 曲率动画的输出可以比输入的范围更广. 例如, 弹性曲线, 如曲线, 弹性值将明显超过或低于默认值.
Tween
默认情况下, AnimationController对象的范围从0到0. 如果您需要一个不同的范围或不同的数据类型, 您可以使用补间来配置一个动画,以便将其插入到不同的范围或数据类型中. 例如, 下面的补间从-200.0到0.0范围.
final Tween doubleTween = Tween<double>(begin: -200.0, end: 0.0);
Tween是一个无状态的对象, 它只接受开始和结束. Tween的唯一工作是定义一个从输入范围到输出范围的映射. 输入范围通常是0到1.0, 但这不是必需的.
Tween继承自Animatable<T>, 而不是Animation<T>. Animatable就像Animation,不是必须输出double. 例如, ColorTween指定了两种颜色之间的变化.
final Tween colorTween =
ColorTween(begin: Colors.transparent, end: Colors.black54);
Tween是一个无状态的对象, 它只接受开始和结束. Tween的唯一工作是定义一个渐变对象不存储任何状态. 相反, 它提供了将映射函数应用到动画当前值的'evaluate(Animation<double> animation)'方法。动画对象的当前值可以在.value方法中找到. evaluate方法也做一些内部处理,例如确保在动画值分别为0.0和1.0时返回开始和结束。
Tween.animate
使用Tween对象, 必须调用'animate()', 并且传递controller对象. 比如, 下面的代码实现了数字在500ms内从0到255变化的过程.
final AnimationController controller = AnimationController(
duration: const Duration(milliseconds: 500), vsync: this);
Animation<int> alpha = IntTween(begin: 0, end: 255).animate(controller);
注意'animate()'返回的是Animation对象而不是Animatable对象.
下面的代码演示了controller, curve, Tween:
final AnimationController controller = AnimationController(
duration: const Duration(milliseconds: 500), vsync: this);
final Animation curve =
CurvedAnimation(parent: controller, curve: Curves.easeOut);
Animation<int> alpha = IntTween(begin: 0, end: 255).animate(curve);
Animation notifications
一个Animation对象可以通过addListener()
和addStatusListner()
拥有Listeners和 StatusListener回调. 当值有任何变化时, Listener都会被回调. 最常规的做法就是在回掉里调用setState()
让UI重建. StatusListener会在动画开始, 结束, 前进, 或反转时被调用.