美文网首页
Flutter 之 动画1

Flutter 之 动画1

作者: Cat_uncle | 来源:发表于2022-03-10 22:23 被阅读0次

    对动画系统而言,为了实现动画,它需要做三件事儿:1.确定画面变化的规律;2.根据这个规律,设定动画周期,启动动画;3.定期获取当前动画的值,不断地微调、重绘画面。

    这三件事情对应到 Flutter 中,就是 Animation、AnimationController 与 Listener:

    1.Animation 是 Flutter 动画库中的核心类,会根据预定规则,在单位时间内持续输出动画的当前状态。Animation 知道当前动画的状态(比如,动画是否开始、停止、前进或者后退,以及动画的当前值),但却不知道这些状态究竟应用在哪个组件对象上。换句话说,Animation 仅仅是用来提供动画数据,而不负责动画的渲染。

    2.AnimationController 用于管理 Animation,可以用来设置动画的时长、启动动画、暂停动画、反转动画等。

    3.Listener 是 Animation 的回调函数,用来监听动画的进度变化,我们需要在这个回调函数中,根据动画的当前值重新渲染组件,实现动画的渲染。

    class NormalAnimateWidget extends StatefulWidget {

    @override

      StatecreateState()=>_NormalAnimateState();

    }

    class _NormalAnimateState extends Statewith SingleTickerProviderStateMixin{

    AnimationController?controller;

    Animation?animation;

    @override

      void initState() {

    // TODO: implement initState

        super.initState();

    /*

    * AnimationController

    AnimationController用于控制动画,它包含动画的启动forward()、停止stop() 、反向播放 reverse()等方法。

    * AnimationController会在动画的每一帧,就会生成一个新的值。

    * 默认情况下,AnimationController在给定的时间段内线性的生成从 0.0 到1.0(默认区间)的数字。

    * */

    /*Ticker

    当创建一个AnimationController时,需要传递一个vsync参数,

    它接收一个TickerProvider类型的对象,它的主要职责是创建Ticker,定义如下:

    abstract class TickerProvider {

    //通过一个回调创建一个Ticker

    Ticker createTicker(TickerCallback onTick);

    }

    Flutter 应用在启动时都会绑定一个SchedulerBinding,

    通过SchedulerBinding可以给每一次屏幕刷新添加回调,

    而Ticker就是通过SchedulerBinding来添加屏幕刷新回调,这样一来,

    每次屏幕刷新都会调用TickerCallback。

    使用Ticker(而不是Timer)来驱动动画会防止屏幕外动画(动画的UI不在当前屏幕时,如锁屏时)

    消耗不必要的资源,因为Flutter中屏幕刷新时会通知到绑定的SchedulerBinding,

    而Ticker是受SchedulerBinding驱动的,

    由于锁屏后屏幕会停止刷新,所以Ticker就不会再触发。

    */

    // 创建动画周期为1秒的AnimationController对象

        controller =AnimationController(

    vsync:this, duration:const Duration(milliseconds:3000));

    /*

    * Curve

    * 动画过程可以是匀速的、匀加速的或者先加速后减速等。

    * Flutter中通过Curve(曲线)来描述动画过程,

    * 我们把匀速动画称为线性的(Curves.linear),而非匀速动画称为非线性的。

    * 我们可以通过CurvedAnimation来指定动画的曲线,如:

    final CurvedAnimation curve =

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

    *

    Curves曲线 动画过程

    linear 匀速的

    decelerate 匀减速

    ease 开始加速,后面减速

    easeIn 开始慢,后面快

    easeOut  开始快,后面慢

    easeInOut  开始慢,然后加速,最后再减速

    *

    * 当然我们也可以创建自己Curve,例如我们定义一个正弦曲线:

    class ShakeCurve extends Curve {

    @override

    double transform(double t) {

    return math.sin(t * math.PI * 2);

    }

    }

    * */

        final CurvedAnimation curve =CurvedAnimation(

    parent:controller!, curve:Curves.linear);

    /*

    * Animation

    *Animation是一个抽象类,它本身和UI渲染没有任何关系,

    * 而它主要的功能是保存动画的插值和状态;其中一个比较常用的Animation类是Animation。

    * Animation对象是一个在一段时间内依次生成一个区间(Tween)之间值的类。

    * Animation对象在整个动画执行过程中输出的值可以是线性的、曲线的、一个步进函数或者任何其他曲线函数等等,

    * 这由Curve来决定。 根据Animation对象的控制方式,

    * 动画可以正向运行(从起始状态开始,到终止状态结束),

    * 也可以反向运行,甚至可以在中间切换方向。

    * Animation还可以生成除double之外的其他类型值

    * ,如:Animation 或Animation。

    * 在动画的每一帧中,我们可以通过Animation对象的value属性获取动画的当前状态值。

    #动画通知

    我们可以通过Animation来监听动画每一帧以及执行状态的变化,Animation有如下两个方法:

    addListener();它可以用于给Animation添加帧监听器,

    * 在每一帧都会被调用。

    * 帧监听器中最常见的行为是改变状态后调用setState()来触发UI重建。

    addStatusListener();

    * 它可以给Animation添加“动画状态改变”监听器;

    * 动画开始、结束、正向或反向(见AnimationStatus定义)时会调用状态改变的监听器。

    * */

    // 创建从50到200线性变化的Animation对象

    // 普通动画需要手动监听动画状态,刷新UI

        animation =Tween(begin:10.0, end:200.0).animate(curve)

    ..addListener(()=>setState((){}));

    /*

    * Tween

    * 默认情况下,AnimationController对象值的范围是[0.0,1.0]。

    * 如果我们需要构建UI的动画值在不同的范围或不同的数据类型,

    * 则可以使用Tween来添加映射以生成不同的范围或数据类型的值。

    *Tween构造函数需要begin和end两个参数。

    * Tween的唯一职责就是定义从输入范围到输出范围的映射。

    * 输入范围通常为[0.0,1.0],但这不是必须的,我们可以自定义需要的范围。

    * */

    // 启动动画

        controller!.repeat(reverse:true);

    //

    // 第二段

    // animation!.addStatusListener((status) {

    //  if (status == AnimationStatus.completed) {

    //    controller!.reverse();// 动画结束时反向执行

    //  } else if (status == AnimationStatus.dismissed) {

    //    controller!.forward();// 动画反向执行完毕时,重新执行

    //  }

    // });

    // controller!.forward();// 启动动画

      }

    @override

      Widget build(BuildContext context) {

    return MaterialApp(

    home:Scaffold(

    body:Center(

    child:Container(

    width:animation!.value,// 将动画的值赋给 widget 的宽高

                      height:animation!.value,//

                      child:FlutterLogo(),

    )

    )

    )

    );

    }

    @override

      void dispose() {

    // 释放资源

        controller!.dispose();

    super.dispose();

    }

    }

    相关文章

      网友评论

          本文标题:Flutter 之 动画1

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