我系苍王,多谢观看我这一个系列的课程,之前分析了Small插件化源码分析,近来看了Android里面的动画框架的相关代码,希望对感兴趣的同学一些帮助。
这一节,我要介绍的是AnimatorSet。
一提到android的动画,一定会涉及到AnimatorSet,因为他太好用了。它所封装的接口让很多复杂的动画叠加变得容易。
AnimatorSet是继承于Animator这个是非常重要的,因为AnimatorSet可以不停的叠加自身,最重要的是他本身就是一个Animator。

我们看一下他播放动画的方法,可以看到它返回的一个Builder的对象,可以推断它是使用建造者的形式,不断迭代动画。

我们看一下他实际构造的时候使用,保存在mCurrentNode的Node对象里面,Node应该是节点的意思。
每个动画都应该由节点构成

其Builder里面存在着三种排序,with,before,after(字面意思应该都很清晰)
(1)with的节点可以看到他是通过Dependency的方法来填充到mCurrentNode里面的,很明显with是并行的

我们可以看到Dependency是只有WITH和AFTER两个时序。

(2)当使用before的时候,相对于mCurrentNode是node节点之后,所以传入mCurrentNode到里面

(3)当使用after的时候,相当于node节点是mCurrent节点之后,所以传入node到里面

使用after延时,其实只是使用一个虚设一个ValueANimator来设定延时时间。

然后我们看一下动画叠加真正的做法。
(1)playTogethor其实是使用with循环的叠加,其参数是不定量的数组的items

我们可以传入Collection的对象,意味着我们可以传入一个列表的Animator

(2)playSequentially是不断使用before来将动画放在之后叠加

setTarget的方法是循环获取node节点的animator动画,终节点通过ObjectAnimator来设置view目标

setInterpolator设置时间插值器,这个插值器最后会在start的方法中是使用

我们接下来看一下动画播放的流程
(1)start的方法会先设置一些标志位,然后通过遍历节点node的animator对象来设置播放同步为false
遍历设置每个动画对象的运行时间
还会设置每个对象的时间插值器

当使用play,playTogethor,playSequentially的时候还会标志需要排列节点,如果node节点没有依赖关系的话,全部会被排列到父节点里面,然后再次循环移除node的依赖父节点,加入到tmproot次节点之后,这样会建立一个统一的mSortedNodes的数组

然后通过遍历mSortedNodes数组移除旧的监听器,
设置nodesToStart来控制全部的节点,
然后再次添加上对应的DependecyListener和AnimatorSetListerner

如果判断延时少于0 ,就把节点的animator播放,并加到mPlayingSet里面,
否则添加值ValueAnimator作为延迟空效果,并通过监听器来在遍历播放节点

通过通过回调来调用每个节点监听器的onAnimationStart,
如果判断节点内其全部的节点都被执行完,木有延迟,那么触发节点的onAnimationEnd的方法

start的方法其实还需要涉及到DependecyListener
这里可以看明白,器通过调用onANimationStart和onAnimationEnd判断运行rule的规则来判断是否启动动画

通过判断父AnimatorSet是否被取消返回
然后判断移除dependencies依赖关系
当全部依赖关系满足的时候,就开启动画

(2)使用pause的方法,会让所有延迟的方法暂停,然后调用每个节点里的pause方法

然后循环调用节点里面的onAnimationPause的方法,暂停每个动画。

pause的方法是停止在中间的状态。
resume的方法也是类似的,用来恢复当前pause状态的动画运行
(3)canel的方法中,需要判断是否正在播放
如果正在播放会全部调用节点onAnimationCancel的方法,
然后再遍历调用延时动画的cancel方法和节点动画的cancel方法。
最后出发节点的onAnimationEnd的方法。

触发剩余调用节点onAnimationCancel的方法,

将全部动画监听器移除,将mPlayingSet的动画移除
将剩下的动画onDone状态设置为false,
触发节点的onAnimationEnd的回调方法

cancel之后动画会停留在中间运行的状态
(4)另外一种end的方法也是可以停止动画运行,
可以看到会停止掉延迟,
然后调用每个动画的end方法和onAnimationEnd的方法,
最后设置回start的标志

end和cancel的不同是,调用了end的方法,它会把动画直接发生整个动画的最后一帧然后停止。
关于AnimatorSet的源码分析就到这里了。
下一节内容敬请期待!!!
网友评论
代码片段
```