美文网首页
flutter-动画

flutter-动画

作者: Liu_QT | 来源:发表于2021-11-08 15:04 被阅读0次

    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<T> animate(Animation<double> parent) {
        return _AnimatedEvaluation<T>(parent, this);
      }
    

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

    T get value => _evaluatable.evaluate(parent);
         ....
      class _AnimatedEvaluation<T> extends Animation<T> with AnimationWithParentMixin<double> {
         _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<double> 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<double> animation})
          : super(key: key, listenable: animation);
    
      Widget build(BuildContext context) {
        final Animation<double> 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-动画

          本文链接:https://www.haomeiwen.com/subject/hxnmzltx.html