Flutter 动画

一、基本的动画概念和类

  • Animation:Flutter动画库中的一个核心类,它生成指导动画的值。
  • AnimationController:管理Animation。
  • Tween:用来定义动画的执行区间。例如,Tween可能会生成从红到蓝之间的色值,或者从0到255。
  • CurvedAnimation:定义一个非线性曲线的动画.
  • Listeners:监听动画的运行过程。
  • StatusListeners:监听动画状态改变。

1、Animation

Animation对象是指在规定时间和区间内生成动画值的类。Animation对象的输出可以是线性的、曲线的、一个步进函数或者任何其他可以设计的映射。 根据Animation对象的控制方式,动画可以反向运行,甚至可以在中间切换方向。

Animation 生成的类型值很多,如:Animation<double>、Animation<Color> 、 Animation<Size>等。

Animation对象有状态。可以通过(value)属性获取动画的当前值,(isCompleted)判断动画是否完成,(isDismissed)判断动画是否在开始时停止动画

Animation对象本身和UI渲染没有任何关系。

2、AnimationController

AnimationController是一个较为特殊的Animation对象,用来控制管理Animation。但AnimationController是Animation<double>的子类,因此可以在需要Animation对象的任何地方使用。默认情况下,AnimationController在给定的持续时间内线性生成从0.0到1.0的值。

AnimationController controller = new AnimationController(
    duration: const Duration(milliseconds: 2000), vsync: this);

上述是AnimationController 对象的创建方式,构造函数第一个参数是动画执行的时间,第二个vsync传入是防止动画离屏之后继续消耗资源。AnimationController 提供了几个常用的方法。

  • forward():启动动画;
  • reverse({double from}:倒放动画;
  • reset():重置动画,将其设置到动画的开始位置;
  • stop({ bool canceled = true }):停止动画。

3、Tween

默认情况下,AnimationController的区间是0.0到1.0,如果我们需要不同的范围或者不同类型的区间时,就可以使用Tween来设置不同类型的区间范围。Tween是一个无状态(stateless)对象,需要beginend值。Tween的唯一职责就是定义从开始到结束区间的映射。如颜色区间映射范围:

final Tween<Color> doubleTween = new Tween(begin: Colors.red, end: Colors.blue);

Tween继承自Animatable<T>。Tween对象不存储任何状态,但它提供了一下方法:

  • T evaluate(Animation<double> animation):方法将映射函数应用于动画当前值。
  • Animation<T> animate(Animation<double> parent):需要传入一个控制器,来获取Animation对象。

4、CurvedAnimation

CurvedAnimation 将动画过程定义为一个非线性曲线,其创建方式如下:

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

parent:参数为需要传入的控制器,

curve:参数为控制动画的非线性曲线,在Curves中已经定义了很多属性,当然我们也可以自定义。

class ShakeCurve extends Curve {
  @override
  double transform(double t) {
    return math.sin(t * math.PI * 2);
  }
}

5、Listeners:监听动画的输出过程。

通过AnimationController对象调用addListener()来实现对动画的输出过程进行监听。 只要动画的值发生变化,就会调用监听器。一个Listener最常见的行为是调用setState()来触发UI重建。

6、StatusListeners:监听动画状态改变。

通过AnimationController对象调用addStatusListener()来实现对动画的状态进行监听。比如动画开始、结束、向前移动或向后移动时会调用StatusListener。

 

二、基础动画实现 

前面已经介绍了基本动画的类和属性,那么我们来看一下平移、旋转、透明、缩放这些基础动画如何实现。

1、平移动画

通过SlideTransition来实现平移动画,附上代码
class Translate extends StatefulWidget {
  @override
  createState() => TranslateState();
}
class TranslateState extends State<Translate> with TickerProviderStateMixin {
  AnimationController controller;
  Animation<Offset> animation;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    controller = AnimationController(vsync: this, duration: Duration(seconds: 2));
    controller.addStatusListener((status) {
      if (controller.isCompleted) {
        controller.reverse();
      } else if (controller.isDismissed) {
        controller.forward();
      }
    });
    animation = Tween(begin: Offset.zero, end: Offset(3.0, 0)).animate(controller);
    controller.forward();
  }
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      alignment: Alignment.topLeft,
      decoration: BoxDecoration(border: Border.all(color: Colors.black,width: 2)),
      padding: EdgeInsets.all(10),
      height: 100,
      child: SlideTransition(
        position: animation,
        child: new Container(  width: 80, height: 80, color: Colors.red),
      ),
    );
  }
}

2、旋转动画

通过RotationTransition实现旋转动画,附上代码

class Rotation extends StatefulWidget {
  @override
  createState() => RotationState();
}
class RotationState extends State<Rotation>
    with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation<double> rotation;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    controller = new AnimationController(vsync: this, duration: Duration(seconds: 2));
    controller.addStatusListener((state) {
      if (controller.isCompleted) {
        controller.reverse();
      } else if (controller.isDismissed) {
        controller.forward();
      }
    });
    rotation = new Tween(begin: 1.0, end: 0.1).animate(controller);
    controller.forward();
  }
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      alignment: Alignment.center,
      decoration: BoxDecoration(border: Border.all(color: Colors.black,width: 2)),
      padding: EdgeInsets.all(10),
      height: 100,
      child: RotationTransition(
        turns: rotation,
        child: new Container( width: 80, height: 80, color: Colors.red, ),
      ),
    );
  }
}

3、透明动画

通过FadeTransition实现透明动画

class Alpha extends StatefulWidget {
  @override
  createState() => AlphaState();
}
class AlphaState extends State<Alpha> with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation<double> alpha;
  @override
  void initState() {
    super.initState();
    controller = new AnimationController(vsync: this, duration: Duration(seconds: 2));
    controller.addStatusListener((state) {
      if (controller.isCompleted) {
        controller.reverse();
      } else if (controller.isDismissed) {
        controller.forward();
      }
    });
    alpha = new Tween(begin: 1.0, end: 0.5).animate(controller);
    controller.forward();
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      decoration: BoxDecoration(border: Border.all(color: Colors.black,width: 2)),
      padding: EdgeInsets.all(10),
      child: FadeTransition(
        opacity: alpha,
        child: new Container( width: 100, height: 100, color: Colors.deepPurpleAccent),
      ),
    );
  }
}

4、缩放动画

通过ScaleTransition实现缩放动画

class Scale extends StatefulWidget {
  @override
  createState() => ScaleState();
}
class ScaleState extends State<Scale> with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation<double> scale;
  @override
  void initState() {
    super.initState();
    controller = new AnimationController(
        vsync: this, duration: Duration(seconds: 2));
    controller.addStatusListener((state){
      if (controller.isCompleted) {
        controller.reverse();
      } else if (controller.isDismissed) {
        controller.forward();
      }
    });
    scale = new Tween(begin: 1.0,end: 0.1).animate(controller);
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      alignment: Alignment.center,
      decoration: BoxDecoration(border: Border.all(color: Colors.black,width: 2)),
      padding: EdgeInsets.all(10),
      height: 100,
      child: new ScaleTransition(
        scale: scale,
        child: new Container( width: 80, height: 80, color: Colors.red, ),
      ),
    );
  }
}

实现效果:

             

 

三、并行动画和串行动画的实现:

1、并行动画

并行动画是指两个及两个以上的动画同时运行。

例如:视图在平移的同时视图从矩形变成圆形。

class Parallel extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return ParallelDemoState();
  }
}
class ParallelDemoState extends State<Parallel> with SingleTickerProviderStateMixin {
  Tween<double> slideTween = Tween(begin: 0.0, end: 300.0);
  Tween<double> borderTween = Tween(begin: 0.0, end: 40.0); // 添加边角半径变动范围
  Animation<double> slideAnimation;
  Animation<double> borderAnimation; // 添加边角半径动画定义
  AnimationController controller;
  @override
  void initState() {
    controller = AnimationController(duration: Duration(seconds: 2), vsync: this);
    slideAnimation = slideTween.animate(CurvedAnimation(parent: controller, curve: Curves.decelerate));
    borderAnimation = borderTween.animate(CurvedAnimation(parent: controller, curve: Curves.linear)); // 定义边角半径动画

    controller.addStatusListener((state) {
      double dd = slideAnimation.value;
      if (controller.isCompleted) {
        controller.reverse();
      } else if (controller.isDismissed) {
        controller.forward();
      }
    });
    controller.addListener((){
      setState(() {

      });
    });
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.topLeft,
      decoration: BoxDecoration(border: Border.all(color: Colors.black,width: 2)),
      padding: EdgeInsets.all(10),
      width: 200,
      child: Container(
        margin: EdgeInsets.only(left: slideAnimation.value),
        width: 80,
        height: 80,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(borderAnimation.value),
          color: Colors.blue,
        ),
       
      ),
    );
  }
}

2、串行动画

串行动画是指动画一个接一个的执行。

例如:动画平移之后在从矩形变成圆形。

class Sequential extends StatefulWidget {
  @override
  createState() => SequentialState();
}

class SequentialState extends State<Sequential> with SingleTickerProviderStateMixin {
  AnimationController controller;
  Tween<double> slideTween = Tween(begin: 0.0, end: 200.0);
  Tween<double> borderTween = Tween(begin: 0.0, end: 40.0); // 添加边角半径变动范围
  Animation<double> slideAnimation;
  Animation<double> borderAnimation;

  @override
  void initState() {
    controller =
        AnimationController(duration: Duration(seconds: 2), vsync: this);
    slideAnimation = slideTween.animate(  CurveTween(curve: Interval(0.0, 0.5, curve: Curves.linear)).animate(controller));
    borderAnimation = borderTween.animate(CurveTween(curve: Interval(0.5, 1.0, curve: Curves.linear)).animate(controller));
    controller.addStatusListener((state) {
      if (controller.isCompleted) {
        controller.reverse();
      } else if (controller.isDismissed) {
        controller.forward();
      }
    });
    controller.addListener((){
      setState(() {
      });
    });
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(10),
      decoration: BoxDecoration(
        border: Border.all(color: Colors.black, width: 2),
      ),
      alignment: Alignment.centerLeft,
      child: Container(
        width: 80,
        height: 80,
        margin: EdgeInsets.only(left: slideAnimation.value),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(borderAnimation.value),
          // 边角半径的属性上添加动画
          color: Colors.blue,
        ),
      ),
    );
  }
}

效果图:

                

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值