一个小型的 Flutter 开发示例将帮助您理解动画,动画
APP里充满了不同的动画,有的用GIF,有的Flare,有的Lottie...
对于Flutter原生的动画来说,也是非常强大的。
这里有一个小例子:
底部的箭头“会向上移动并逐渐变得透明,然后重复该动作”。稍后我们会讲如何实现。首先,我们来谈谈Flutter中动画的基础知识。
动画的类型
首先,Flutter中的动画分为两类:
- 附加动画(Tween)
- 我们常用的是基于物理的动画,其中我们常用的是动画。含义引自《Flutter中文网》解释:
“Between”的缩写。在完成的动画中,定义了起始点和结束点、时间线以及定义过渡时间和速度的曲线。然后框架计算如何从起点到达终点。
其实动画是由一系列图像组成的,补间动画根据时间计算出如何走,然后向我们展示这一系列图像。
动画
Flutter中的动画系统是基于“Animation”的。 “Widgets”可以直接将这些动画合并到它们自己的构建方法中,以读取它们的当前值或跟踪它们的状态变化,或者它们可以用作传递给其他小部件的更复杂动画的基础。
Animation是一个抽象类,它的主要功能是存储动画的状态和值。
一般使用
.addListener
方法添加监听器。您可以在此侦听器中获取当前状态和值,但只要发生操作,此侦听器就会回调。如果您只想监听当前状态,那么只需使用.addStatusListener 方法即可。
“动画”有以下几种状态:
- 关闭:一般情况下动画都是从这个状态开始的
- forward:运行时可以是这样
- backward: :运行时也可以是这样 Completed:完成后就变成了这个
AnimationController
要创建动画,首先要创建一个
AnimationController
。除了Animation
本身之外,AnimationController
也可用于控制动画。例如,让动画向前播放和停止。既然需要先创建
AnimationController
,我们先看看它的构造函数来了解如何创建它:AnimationController({ double value, this.duration, this.reverseDuration, this.debugLabel, this.lowerBound = 0.0, this.upperBound = 1.0, this.animationBehavior = AnimationBehavior.normal, @required TickerProvider vsync, }) : assert(lowerBound != null), assert(upperBound != null), assert(upperBound >= lowerBound), assert(vsync != null), _direction = _AnimationDirection.forward { _ticker = vsync.createTicker(_tick); _internalSetValue(value ?? lowerBound); } 复制代码
参数说明: eueu duration:duration
- re诗句持续时间:反向持续时间动画
- debugLabel:用于调试的字符串
- lowerBound:下限,动画可以获取且已取消的最小值不能为空。
- upperBound:上限,动画可以获得的最大值,动画结束时的值。它不能为空。
- animationBehavior:配置禁用动画时的[AnimationController]行为。
- vsync:当前上下文的 TickerProvider,可以使用
resync
进行更改。它不能为空。需要
垂直同步。在带动画的类后面加上和TickerProviderStateMixin
就可以了。
Tween
由于AnimationController
的默认值为0 - 1,如果要设置0 - 1以外的值,则必须使用Tween开始值和结束值。 Tween是最常用的,但也有很多具体的Tween类型:
- ColorTween
- SizeTween
- TweenCurveTween...只是定义了如何在两个值之间进行插值。如果您想要当前的具体值,您仍然需要动画。这里有两种方法可以获取当前状态的具体参考:
- evaluate:这种方法适合已经写好的动画,并且在该动画在小部件运行时重建小部件时更有效。
- animate:此方法返回一个适合使用此小部件为小部件创建新动画的动画。
要实现一开始的效果
先想一下这个效果:“向上滚动,逐渐变成透明,然后重复这个动作。”
- 向上滚动:我们利用容器的边框属性
- 逐渐透明:应用Opacity图层,利用opacity属性来实现
- 重复动作:找出动画当前的状态,然后重新开始
明白需求后,我们先写控件。
由于我们的动画效果有点复杂,所以我们使用
AnimatedWidget
来封装组件,避免大量重复setState。所以,Widget的动画代码如下:
class AnimatedUpArrow extends AnimatedWidget { final Tween<double> _opacityTween = Tween(begin: 1, end: 0); final Tween<double> _marginTween = Tween(begin: 0, end: 50); AnimatedUpArrow({Key key, Animation<double> animation}) : super(key: key, listenable: animation); @override Widget build(BuildContext context) { final Animation<double> animation = listenable; return SafeArea( child: Center( child: Opacity( opacity: _opacityTween.evaluate(animation), child: Container( margin: EdgeInsets.only(bottom: _marginTween.evaluate(animation)), child: Image.asset("images/UP.png", width: 20, height: 24,), ), ), ), ); } } 复制代码
首先创建两个补间。由于两个动画是同时执行的,因此最好使用Tween求值方法通过动画来计算插值。
代码很简单,然后看看如何使用这个小部件:
AnimationController _animationController; Animation<double> _animation; @override void initState() { super.initState(); _animationController = AnimationController( vsync: this, duration: Duration(milliseconds: 1400)); _animation = CurvedAnimation(parent: _animationController, curve: Curves.linear); _animationController.addStatusListener((status) { if (status == AnimationStatus.completed) { Future.delayed(Duration(milliseconds: 500), () { _animationController.reset(); }); } else if (status == AnimationStatus.dismissed) { _animationController.forward(); } }); _animationController.forward(); } @override Widget build(BuildContext context) { return AnimatedUpArrow( animation: _animation, ); } 复制代码
简单解释:
首先定义
AnimationControllerAnimationController
为持续时间0,0,0然后定义 动画,立即将控制器设置为控制器,将曲线设置为线性,,然后定义动画完成的
❝StatusListener。如果完成,500毫秒后执行。延迟后,动画重置并继续动画,创建重复动画效果。
最后,在build方法中传入集合
Animation
,这样就可以使用刚才定义的AnimatedWidget
来根据插值来计算这个动画了现在顶部动画就准备好了。
总结
Flutter 中很多原生 Widget 都使用了
AnimatedWidget
,例如AnimatedPositioned❙。看它的构建方法:
@override Widget build(BuildContext context) { return Positioned( child: widget.child, left: _left?.evaluate(animation), top: _top?.evaluate(animation), right: _right?.evaluate(animation), bottom: _bottom?.evaluate(animation), width: _width?.evaluate(animation), height: _height?.evaluate(animation), ); 复制代码
OK 可以看到和我们上面使用的方法是一样的,就是评估方法。
作者:颤笔记
链接:https://juejin.im/post/5d646c9e6fb9a06b084d037e
来源:掘金商业转载请联系作者授权。非商业转载请注明出处。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。