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会在动画开始, 结束, 前进, 或反转时被调用.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容