内容简介:本例的代码参考动画处理的基本原理是,对组件(widget)的某个或某组属性设置一组连续变化的值,这些值在一定时间间隔内不断被应用到该属性上,使得组件的外观看上去在进行平滑而连续的变动。例如2秒内每隔0.1s将一个组件的x轴坐标加1,那么该组件看上去就是从左至右移动了2秒共20个单位。
本例的代码参考 这里 。
概述
动画处理的基本原理是,对组件(widget)的某个或某组属性设置一组连续变化的值,这些值在一定时间间隔内不断被应用到该属性上,使得组件的外观看上去在进行平滑而连续的变动。
例如2秒内每隔0.1s将一个组件的x轴坐标加1,那么该组件看上去就是从左至右移动了2秒共20个单位。
处理组成部分
具体到Flutter,动画处理主要分为三个部分:
- 动画控制器(AnimationController),控制整个动画运行,包括开始结束和动画时长等。
- 动画抽象(Animation),描述了动画运动的速率,例如组件是加速还是匀速,或者其它变化。
- 变动范围(Tween),定义了动画组件属性值的变化范围,例如从坐标(0, 0)移动到(20, 0)
处理流程
上述三大组件,控制了整个动画的运行。用文字描述,其流程主要包括:
- 初始化动画控制器,设定动画的时长,初始值等(如上例:2秒时长)
- 初始化变动范围(如上例:Offset从[0, 0]到[20, 0])
- 初始化动画抽象,定义它的运动速率(如上例:匀速变动)
- 将动画描述的值,赋值到动画组件的对应属性上
- 开始执行动画(调用动画控制器的开始方法)
- 动画执行结束
AnimationController定义
AnimationController是一个特殊的Animation对象。创建一个AnimationController时,需要传递一个vsync参数。设置此参数的目的,是希望屏幕每一帧画面变化时能够被通知到。也就是说,屏幕刷新的每一帧,AnimationController都会生成一个新的值(同样也意味着,如果在屏幕外那么就不被触发)。这样动画组件就能够完成一个连续平滑的动画动作。
Tickers can be used by any object that wants to be notified whenever a frame triggers。
AnimationControler通常是在一个StatefulWidget中被声明,并且附带一个叫做SingleTickerProviderStateMixin的Mixin(原因就在上面说的,要设置vsync参数)。
class AnimationDemo extends StatefulWidget { AnimationDemoState createState() => AnimationDemoState(); } class AnimationDemoState extends State<AnimationDemo> with SingleTickerProviderStateMixin { AnimationController controller; @override void initState() { super.initState(); controller = AnimationController(duration: Duration(milliseconds: 2000), vsync: this); ... } @override void dispose() { controller.dispose(); // 离开时需要销毁controller super.dispose(); } ... }
当Animation和Tween的设置完成后,简单调用controller.forward()即可开始动画。
Tween定义
Tween就是要改变的属性值的变动范围。它可以是任意的属性类如Offset或者Color,最常见的是double。
... AnimationController controller; Tween<double> slideTween = Tween(begin: 0.0, end: 20.0); ...
Animation定义
Animation对象本身可以看做是动画中所有变化值的一个集合。它包含了变化区间内的所有可取值,并返回给动画组件当前的变动值。
Animation在使用中要设置的,是他的变动速率,如Curves.linear(线性变化)。
... AnimationController controller; Tween<double> slideTween = Tween(begin: 0.0, end: 20.0); Animation<double> animation; @override void initState() { super.initState(); ... animation = slideTween.animate(CurvedAnimation(parent: controller, curve: Curves.linear)); } ...
动画组件定义
为了说明简单,在build方法中嵌套两个Container组件,外部容器Container的paddingLeft跟随动画变动,达到移动内部Container的目的。
class AnimationDemoState extends State<AnimationDemo> with SingleTickerProviderStateMixin { ... @override Widget build(BuildContext context) { return Container( width: 200, alignment: Alignment.centerLeft, padding: EdgeInsets.only(left: animation.value), child: Container( color: Colors.blue, width: 80, height: 80, ), ); } }
启动动画
在启动动画之前有一个Flutter的基本概念要说明。做过React的同学很清楚,要想render方法重新执行,要么props有更新要么state有更新。在Flutter也同样如此,build方法同样依赖于state的更新才能重新执行。
在AnimationController的说明中,我们知道因为设置了vsync所以屏幕刷新的每一帧都会更新它的值。所以可以在Controller上加上一个listener,每次有update都调用一下setState,以此达到重新渲染UI的目的。
... @override void initState() { ... animation.addListener(() => this.setState(() {})); controller.repeat(); // 动画重复执行 }
调用controller.repeat()方法,动画会被反复执行。如果想只执行一次,那么可以使用controller.forward();
以上所述就是小编给大家介绍的《Flutter尝鲜2——动画处理<基础>》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
从“为什么”开始
[美] 西蒙·斯涅克 / 苏西 / 海天出版社 / 2011-7 / 32.00元
影响人类的行为:要么靠操纵,要么靠感召。 操纵带来的是交易,是短期效益; 感召带来的是信任,是永续经营! 盖茨走后,微软面临怎样的挑战?后盖茨时代,微软为何从一个希望改变世界的公司沦落为一个做软件的公司? 沃尔玛的灵魂人物过世后,一度被人们热爱的公司,遭到的竟然多是顾客、员工的反感?沃尔玛要怎样做才能重放昔日光彩? 星巴克吸引人们购买的不是咖啡,而是理念?为什么说霍华......一起来看看 《从“为什么”开始》 这本书的介绍吧!