先看入口函数:
参数很熟悉了,具体看里面做了什么,其实也很简单,创建一个实例对象,并将参数设置到对象中。 第一个参数暂时先不看,看第二个参数,**anim.setObjectValues(values)**
重点是 valuesHolder.setObjectValues(values);
这里把输入的参数值传给了 KeyframeSet这个类,这个类很重要!
在KeyframeSet 里面,将所有的参数值保存到一个 Keyframe数组中,这个Keyframe可以类比Map,键值对保存参数值,其中key是fraction,也就是随时间变化的系数,但是这个里面是根据数组下标占总数的百分比来求得(这里面就存在一个隐藏坑,具体看《动画插值器源码分析》一文),value就是对应的参数值。
这就是一般创建动画时的执行流程,接着来看动画执行部分!
动画执行先看入口函数:
其中的关键代码如下:
首先是开始执行动画,接着由于这个 **mSeekFraction** 值默认是-1 , 因此后续会进入 setCurrentPlayTime(0);
先来看开始动画,如下图,重要的是进行了动画的初始化 initAnimation(); 。
进入该函数会发现主要是对value值进行了初始化。
初始化代码如下图:
可以看到初始化其实就是设置估值器,也就是 evaluator ,而这个是咱们经常自定义重写的关键类!
开启动画到这里基本就走完了,接着来看初始化动画值!也就是setCurrentPlayTime这个函数了,如下图:
其实他就是调用了之前经常看到的setCurrentFraction 这个函数,顾名思义,该函数就是设置当前的fraction(基于开始时间)。
其中的核心代码就是 animatevalue(currentIterationFraction) 这一行,进入该函数可以看到第一行就出现了我们非常熟悉的东西——Interpolator , 这个东西可以由我们自定义改写其中的规则,当然系统也有写好的供我们使用,他的作用就是将 fraction 按照一定的规则算法改变,而这个fraction从上文可知是和value值一对一匹配的。
接着就是for循环执行 mValues[i].calculatevalue(fraction) ,这行代码的作用就是根据fraction算出具体的动画属性值!如下图:
果然,看到了熟悉的 keyframe ,进去看看!代码很长,但是我还是全部贴出来了,因为都很重要!
这个函数前半部分对只有2个值的情况做了特殊优化,并且对于fraction 超出[0,1]范围的情况做了特殊处理,直接去边界值进行估值计算(这里面就存在一个隐藏坑,具体看 动画插值器源码分析 )!
后半部分代码的作用是从第二帧开始,每一帧的fraction和前一帧的fraction组成一个区域,根据传入的fraction在区域的百分比来执行动画插值,当然这个百分比也是可以通过咱们自己的 Interpolator拦截修改掉的!最后,将这两帧值和百分比fraction传入估值器进行估值!
到此,动画就开始执行了,接着看动画的具体执行!
大家知道Android系统的运行机制是一个无限循环的消息机制,不例外的动画也是一个消息刷新机制,Choreographer这个单词的意思是编舞者,顾名思义,负责动作画面的指导!动画的刷新机制就从这里开始触发!关键代码 doAnimationframe(getProvider().getframeTime());。
进入该行代码,其中的关键代码是 callback.doAnimationframe(frameTime);,而这个callback谁实现了呢?没错,就是 ValueAnimator!
进入ValueAnimator的回调函数中,如下图,代码很长,我会截取其中的关键部分。
可以看到,代码的最后进到了这行代码: animatebasedonTime(currentTime);
这里面首先会根据当前时间和开始时间来计算动画执行的fraction,但是这里需要注意的是如果你是无限循环动画的话,你的fraction有可能不会到1.0 或者0.0 (这里是另一个坑)!因为Android系统的Choreographer 这个函数是根据系统的VSYNC信号来触发的,而VSYNC的数值是和刷新率有关系的!而这个函数会约束fraction在[0,1]之间,却没有保证一定能够到达两端!
接着会先通知OnRepeat回调函数的执行!最后便是上文提到的动画属性值的计算!
到此,整个动画的基本流程已经梳理通畅了!可以愉快的编(写)代(八)码(哥)了!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)