Flutter 动画 3 - Animation 动画组,android 物联网开发李天祥
在前面的两篇博客中,我们了解了在 Flutter 中动画如何简单的使用动画,了解 Tween 相关使用方法.但是在很多场景下,我们使用的并不是单单一种动画,而是多种动画一起执行或者顺序执行,那么在应对这样的场景我们该怎么办呢? 今天,我们就聊一聊如何在 Flutter 中实现这种并行动画或者串行动画呢?接下来我们就一起看看这两种形式的动画是如何实现的.
并行动画
对于并行动画这种多个动画同时执行,我们需要让各个动画 Animation 的动画控制器 AnimationController 保持一致就可以了. 这个在上一篇 Tween 已经进行了对应说明演示.这里就直接把代码拿来了.
首先创建动画并保持动画控制器的统一性.示例如下代码所示.
_animationController = AnimationController(duration: Duration(milliseconds: 300), vsync: this);_animation = Tween<double>(begin: 0, end: 50).animate(_animationController)..addListener(() {setState(() {});});_colorAnimation = ColorTween(begin: Colors.orangeAccent, end: Colors.redAccent).animate(_animationController)..addListener(() {setState(() {});});
然后再构建 build 方法中直接使用_animation 和_colorAnimation 的动画值就好,具体代码如下所示.
Container(width: 200,height: 50,color: _colorAnimation.value,margin: EdgeInsets.only(top: _animation.value),),
串行动画
相对于并行动画而言,串行动画写起来就比较复杂的多,串行动画的实现方案总共有三种,分别是 监听状态法, Interval 时间间隔法, TweenSequence 动画序列法.下面我们就分别来看看三种方法的实现以及区别.
监听状态法
状态监听法主要通过 AnimationController 监听动画的 completed 状态,然后再去执行下一个动画,如此往复,直到所有动画完成.
例如现在我们需要实现先执行组件在 0.3 秒钟往下偏移 50 个单位,然后再执行在 0.6s 中组件的颜色由 橘色 变为 红色 .
首先,我们先声明位移动画控制器和颜色动画控制器以及位移动画和颜色动画,代码如下所示.
AnimationController _animationController;Animation<double> _animation;AnimationController _colorAnimationController;Animation<Color> _colorAnimation;
然后,我们创建位移、颜色的动画控制器和动画,具体代码如下所示.
_animationController = AnimationController(duration: Duration(milliseconds: 300), vsync: this);_animation = Tween<double>(begin: 0, end: 50).animate(_animationController)..addListener(() {setState(() {});});_colorAnimationController = AnimationController(duration: Duration(milliseconds: 600), vsync: this);_colorAnimation = ColorTween(begin: Colors.orangeAccent, end: Colors.redAccent).animate(_colorAnimationController)..addListener(() {setState(() {});});
最后,我们只需要监听位移动画完成状态之后执行颜色动画即可,具体代码如下所示.
_animationController.addStatusListener((status) {if (status == AnimationStatus.completed) {_colorAnimationController.forward();};});
整体 Demo 代码如下所示.
class _FlutterAnimationWidgetState extends State<FlutterAnimationWidget> with TickerProviderStateMixin {AnimationController _animationController;Animation<double> _animation;AnimationController _colorAnimationController;Animation<Color> _colorAnimation;
@overridevoid initState() {super.initState();_animationController = AnimationController(duration: Duration(milliseconds: 300), vsync: this);_animation = Tween<double>(begin: 0, end: 50).animate(_animationController)..addListener(() {setState(() {});});_colorAnimationController = AnimationController(duration: Duration(milliseconds: 600), vsync: this);_colorAnimation = ColorTween(begin: Colors.orangeAccent, end: Colors.redAccent).animate(_colorAnimationController)..addListener(() {setState(() {});});_animationController.addStatusListener((status) {if (status == AnimationStatus.completed) {_colorAnimationController.forward();};});}
void startEasyAnimation() {_animationController.forward();}
@overridevoid dispose() {_animationController.dispose();super.dispose();}
@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Container(width: 200,height: 50,color: _colorAnimation.value,margin: EdgeInsets.only(top: _animation.value),),FlatButton(onPressed: startEasyAnimation,child: Text("点击执行最简单动画",style: TextStyle(color: Colors.black38),),),],),),);}}
Interval 时间间隔法
上面的状态监听需要一个动画过程就写一个 Controller,而且基本上还要每一个 Controller 都监听执行完成然后再去启动下一个 Controller.如果一个动画过程有十几个,自己想想都是脑瓜子嗡嗡的.所以接下来我们就来介绍第二种方案 - Interval 时间间隔法 .
Interval 时间间隔法 的整体思路是一个动画 Controller 控制所有动画的执行.然后每一个动画只需要确认自己在整个动画的时间比重即可.
首先,声明一个动画 Controller 和多个动画.
AnimationController _animationController;Animation<double> _animation;Animation<Color> _colorAnimation;
然后初始化 AnimationController,AnimationController 的动画时间(duration)要设置成所有动画的总时长,例如这里我设定为 600 毫秒(_animation 时长:300 毫秒,_colorAnimation 时长:300 毫秒).
_animationController = AnimationController(duration: Duration(milliseconds: 600), vsync: this);
接下来就是初始化两个 Animation,Tween 对象调用animate()
函数不再是直接传入上面的 AnimationController,而是传入一个 CurvedAnimation 对象.CurvedAnimation 构建过程中需要传入两个参数一个是 parent ,用于指定 AnimationController. 另外一个是 curve,用于指定动画曲线函数.我们可以使用常用的动画曲线函数,也可以自己生成,这里我们就自己生成.指定动画执行的时间区间.
// CurvedAnimation 的构建方法 CurvedAnimation({required this.parent,required this.curve,this.reverseCurve,}) : assert(parent != null),assert(curve != null) {_updateCurveDirection(parent.status);parent.addStatusListener(_updateCurveDirection);}
由于两个动画时间长度是对分的,每一个都是 300 毫秒,所以 curve 参数中的值就分别是 Interval(0.0, 0.5) 、Interval(0.5, 1.0),两个 Animation 的初始化过程如下所示.
_animation = Tween<double>(begin: 0, end: 50).animate(CurvedAnimation(parent: _animationController,curve: Interval(0.0, 0.5),),)..addListener(() {setState(() {});});
_colorAnimation = ColorTween(begin: Colors.orangeAccent, end: Colors.redAccent).animate(CurvedAnimation(parent: _animationController,curve: Interval(0.5, 1.0),),)..addListener(() {setState(() {});});
整体 Demo 代码如下所示.
class _FlutterAnimationWidgetState extends State<FlutterAnimationWidget> with TickerProviderStateMixin {AnimationController _animationController;Animation<double> _animation;Animation<Color> _colorAnimation;
@overridevoid initState() {super.initState();_animationController = AnimationController(duration: Duration(milliseconds: 600), vsync: this);_animation = Tween<double>(begin: 0, end: 50).animate(CurvedAnimation(parent: _animationController,curve: Interval(0.0, 0.5),),)..addListener(() {setState(() {});});_colorAnimation = ColorTween(begin: Colors.orangeAccent, end: Colors.redAccent).animate(CurvedAnimation(parent: _animationController,curve: Interval(0.5, 1.0),),)..addListener(() {setState(() {});});}
void startEasyAnimation() {_animationCo
ntroller.forward();}
@overridevoid dispose() {_animationController.dispose();super.dispose();}
@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Container(width: 200,height: 50,color: _colorAnimation.value,margin: EdgeInsets.only(top: _animation.value),),FlatButton(
评论