flutter-动画

flutter动画

1.动画原理:在一段时间内快速的多次改变UI外观,由于人眼会产生视觉暂留所以最终看到的就是一个连续的动画。
UI的一次改变称为一个动画帧,对应一次屏幕刷新。
FPS:帧率,每秒的动画帧数。

flutter动画分为两类:

  • 补间动画
  • 物理动画

常见动画模式:

  • list、grid中的动画:例如一些元素的添加或者删除。
  • 转场动画
  • 交错动画

基本的动画概念与类:

Animation

是一个抽象类,主要的功能是保存动画的值和状态。常用的一个Animation类是Animation< double >,是一个在一段时间内依次生成一个区间之间的值的类,可以是线性或者曲线或者其他。
可以生成除double之外的其他类型值,如:Animation< Color > 或 Animation< Size >。

AnimationController

是一个动画控制器,控制动画的播放状态,在屏幕刷新的每一帧,就会生成一个新的值。
包含动画的启动forward()、停止stop() 、反向播放 reverse()等方法,在给定的时间段内线性的生成从0.0到1.0(默认区间)的数字。

  • 使用Listeners和StatusListeners监听动画状态改变。
AnimationController controller = AnimationController(
    duration: Duration(milliseconds: 2000), vsync: this);

Curve

curve:描述动画的曲线过程。
curvedAnimation:指定动画的曲线。

final CurvedAnimation curve =
    new CurvedAnimation(parent: controller, curve: Curves.easeIn);

常用Curve:

  • linear:匀速的
  • decelerate:匀减速
  • ease:开始减速后减速
  • easeIn:开始慢后快
  • easeOut:开始快后慢
  • easeInOut:开始慢加速再减速

Tween

继承自Animatable< T >,表示的就是一个 Animation 对象的取值范围,只需要设置开始和结束的边界值(值也支持泛型)。 它唯一的工作就是定义输入范围到输出范围的映射。
例如,Tween可能会生成从红到蓝之间的色值,或者从0到255。

final Tween colorTween =
    new ColorTween(begin: Colors.transparent, end: Colors.black54);

Tween.animate:返回一个Animation。

映射过程:
1). Tween.animation通过传入 aniamtionController 获得一个_AnimatedEvaluation 类型的 animation 对象(基类为 Animation), 并且将 aniamtionController 和 Tween 对象传入了 _AnimatedEvaluation 对象。

Animation animate(Animation parent) {
    return _AnimatedEvaluation(parent, this);
  }

2). animation.value方法即是调用 _evaluatable.evaluate(parent)方法, 而 _evaluatable 和 parent 分别为 Tween 对象和 AnimationController 对象。

T get value => _evaluatable.evaluate(parent);
     ....
  class _AnimatedEvaluation extends Animation with AnimationWithParentMixin {
     _AnimatedEvaluation(this.parent, this._evaluatable);

3). 这里的 animation 其实就是前面的 AnimationController 对象, transform 方法里面的 animation.value则就是 AnimationController 线性生成的 0.0~1.0 直接的值。 在 lerp 方法里面我们可以看到这个 0.0~1.0 的值被映射到了 begin 和 end 范围内了。

T evaluate(Animation animation) => transform(animation.value);

    T transform(double t) {
    if (t == 0.0)
      return begin;
    if (t == 1.0)
      return end;
    return lerp(t);
  }

    T lerp(double t) {
    assert(begin != null);
    assert(end != null);
    return begin + (end - begin) * t;
  }

vsync

接收一个TickerProvider类型的对象,它的主要职责是创建Ticker。
防止屏幕外动画消耗资源。

流程图:

[图片上传失败...(image-115b94-1636441483468)]

总结:

过程:

  • TickerProvider 会创建一个 Ticker, 并将_tick(TickerCallback 类型)回调方法绑定到了 这个 Ticker, 这样 AnimationController 就将回调方法 _tick 和 Ticker 绑定了。
  • Ticker 会在 start 函数内将_tick 被绑定到 SchedulerBinding 的帧回调方法内。
  • SchedulerBinding 则是在构造方法中将自己的 _handleBeginFrame 函数和 window 的 onBeginFrame 绑定了回调。 这个回调会在屏幕需要准备显示帧之前回调。
  • 在 AnimationController 的回调当中, 计算当前的的_value 值, 更新 Animation Status 的状态, 判断是否动画已经结束。 最后通过 notifyListeners 和_checkStatusChanged 方法通知给监听器 value 和 AnimationStatus 的变化。

回调:

ui.window.onBeginFrame = handleBeginFrame;
    ui.window.onDrawFrame = handleDrawFrame;
  • window调用SchedulerBinding的_handleBeginFrame方法
  • SchedulerBinding调用Ticker的_tick方法
  • Ticker调用 AnimationController的_tick的方法,
  • animationContoller通知监听器
  • 而监听器调用widget的setStatus方法来调用build更新
  • build使用了Animation对象当前的值来绘制动画帧

用AnimatedWidget简化

不使用addListener()和setState()来给widget添加动画。
使用AnimatedWidget,将widget分离出来,创建一个可重用动画的widget,AnimatedWidget中会自动调用addListener()和setState()

class AnimatedImage extends AnimatedWidget {
  AnimatedImage({Key key, Animation animation})
      : super(key: key, listenable: animation);

  Widget build(BuildContext context) {
    final Animation animation = listenable;
    return new Center(
      child: Image.asset("imgs/avatar.png",
          width: animation.value,
          height: animation.value
      ),
    );
  }
}

常用控件

AnimatedModalBarrier、DecoratedBoxTransition、FadeTransition、PositionedTransition、RelativePositionedTransition、RotationTransition、ScaleTransition、SizeTransition、SlideTransition

AnimatedBuilder重构

如何渲染过渡,把渲染过程也抽象出来:
AnimatedBuilder的示例包括: BottomSheet、 PopupMenu、ProgressIndicator、RefreshIndicator、Scaffold、SnackBar、TabBar。

转场动画

MaterialPageRoute:平台风格一致的路由切换动画
CupertinoPageRoute:左右切换风格

 Navigator.push(context, CupertinoPageRoute(  
   builder: (context)=>PageB(),
 ));

自定义:PageRouteBuilder

交织动画

1.要创建交织动画,需要使用多个动画对象(Animation)。
2.一个AnimationController控制所有的动画对象。
3.给每一个动画对象指定时间间隔(Interval)

AnimatedSwitcher

可以同时对其新、旧子元素添加显示、隐藏动画.
当AnimatedSwitcher的child发生变化时(类型或Key不同),旧child会执行隐藏动画,新child会执行执行显示动画。

希望大家支持一下,感谢
https://itunes.apple.com/cn/app/id1581903089

v2-1bca865a9a7c1a49e3207e5780e5a865_1440w.jpg

你可能感兴趣的:(flutter-动画)