
Android属性动画
一、简介
在Android3.0为了取代传统诞生的产物,相较于传统动画有着很灵活的优势。
**传统动画:**仅仅只能实现平移、缩放、旋转、淡入淡出这四种效果,并且对Button实现从左上角平移到右下角,点击右下角的Button时,并不能触发click事件,也就是说传统的补间动画并未对View的属性做到修改;以及传统动画仅仅只限于对View及其子类做动画。
**属性动画:**可扩展性较高,实现简单,不仅仅可以实现上述传统动画的四种效果,也可以实现ObjectAnimator对任意对象实现动画效果,并且真正意义上的对属性进行了改变。
二、属性动画的用法
2.1 ValueAnimator
ValueAnimator是属性动画的一个核心类,在第一节中说到了Animator是对value属性值进行操作的,初始值和结束值之间的过渡动画就是通过ValueAnimator.ofFloat(0f,1f)这句关键代码传入的,由于没有传入属性的具体值,因此需要通过addUpdateListener设置监听来观察value值的变化;参数设置完毕后,必须要调用animator.start()启动动画。
但属性动画是非常灵活的,我们也可以设置多个动画中间值,如下:
除了上述可以设置属性动画的API以外,还有其他很多可供开发者选择,如下所示:setRepeatCount和setRepeatMode是重复播放相关的
2.2 ObjectAnimator
第一节中说到属性动画可以对任意对象实现动画效果,而不仅仅只限于View。在属性动画中提供了另一个核心类ObjectAnimator,其继承于ValueAnimator。
相比于ValueAnimator,ObjectAnimator从名字上看似乎更加适合开发者,因为ValueAnimator只不过是对value值进行动画变化,但使用场景似乎有限,因此Google推出了其ObjectAnimator,它可以对任意对象的任意属性实现动画效果。但虽然其功能强大,由于其继承自ValueAnimator,底层还是基于ValueAnimator完成的,由于继承关系,ValueAnimator的一些API,在ObjectAnimator上也能够使用。
其用法和ValueAnimator差不多,这里不做过多说明。这里需要说明以下两个API的作用,其原理在第三节源码解析叙述。
TypeEvaluator:估值器,设置属性值从初始值过渡到结束值 的变化具体数值。
Interpolator:插值器,设置属性值从初始状态,到结束状态的变化规律,有匀速、加速、减速。
2.3 多属性动画
上面代码都是改变某一个属性的动画,例如有如下场景:将Button的x,y坐标从左上角移动到右下角,在这个过程中同时将Button的透明度从1改变到0。
2.4 组合动画
也可以实现组合动画,比如先移动Button的y坐标,再移动x坐标,最后实现透明度的变换。
AnimatorSet 中提供play方法,它会返回一个Animator.Builder的构建者,并且Animator.Builder提供了如下四个方法。
三、源码解析
3.1 ValueAnimator源码
(1)先从ValueAnimator animator = ValueAnimator.ofFloat(0f,1f,5f,3f,10f);开始,可以看出在ofFloat中创建了对象,但ValueAnimator是空的,没什么可看的
疑问:ofFloat传入的参数代表什么?
此处propertyName传入的“”,返回的是PropertyValuesHolder的子类FloatPropertyValuesHolder
属性名最终被保存在了PropertyValuesHolder的mPropertyName属性中
继续往下看FloatPropertyValuesHolder的setFloatValues,在这里将value值交给父类PropertyValuesHolder的setFloatValues处理
这里主要是根据开发者传入的values值,为每一个value值创建一个关键帧,然后将这些关键帧封装到了KeyframeSet中。
总结1:
开发者传入的values目的是为了创建关键帧KeyFrame,最终将传入的所有Value值分装成了关键帧,封装到了KeyFrameSet集合中,根据ofFloat传入属性名称ValueAnimator animator = ValueAnimator.ofFloat(0f,1f,5f,3f,10f);,为每一中属性名创建一个PropertyValuesHolder对象,并且PropertyValuesHolder内部持有KeyFrameSet的对象
回到ValueAnimator的setObjectValues方法,此处想为什么会有mValues == null为空和不为空两种情况了,其实想想在2.3节中的多属性动画可知,当开发者创建了多属性动画时,第创建第二个PropertyValuesHolder对象时,mValues 就不为空了。
(2)animator.start();是怎么播放动画的呢?
调用animateValue(currentIterationFraction);
在ValueAnimator中最终回调到onAnimationUpdate,我们添加监听的位置
3.2 ObjectAnimator解析
下面这句代码的作用其实和ValueAnimator差不多,通过alpha属性创建PropertyValuesHolder对象,里面保存着0f,1f关键帧的KeyFrameSet集合,KeyFrameSet有持有各关键帧。
重点关注start方法,可以看到最后一句又回调到ValueAnimator的start方法
回到ValueAnimator的start,看到一句startAnimation();重点代码
经过一系列调用,最终调用到子类ObjectAnimator的animateValue
最终调用到PropertyValuesHolder的setAnimatedValue,这里关注 mSetter.invoke(target, mTmpValueArray);,先说明这句代码的意义:通过反射调用target View的mSetter方法。
那么mSetter是怎么来的呢?通过以下这句代码拼接而来的,为了方便理解,我自己写了一个setupSetterOrGetter方法
就是通过将属性名的第一个字母大写,然后和"set"和属性名拼接即可
总结:也就是从这里可以得出,属性动画最终是通过反射调用Object的各set方法对Object的各属性设置。
3.3 插值器和估值器
第一次学习属性动画时,当听到别人说插值器和估值器感觉是个很复杂、很高大上的东西,其实不然。
其作用就是:插值器负责计算动画执行的百分比,估值器负责根据百分比来计算属性值。插值器计算完动画执行的百分比后,将Fraction交给估值器计算属性的百分比。
(1)TimeInterpolator:
系统给开发者提供了好几种插值器,现在我们直接看看LinearInterpolator ,这里很容易的理解,getInterpolation的输入和返回成线性比例,开发这也可以自定义插值器,只需要继承Interpolator ,重写getInterpolation。如博主子啊2.2中缩写的input*input,播放速度与时间成平方的关系。
(2)TypeEvaluator估值器
系统也给开发者定义了很多估值器,如颜色属性的ArgbEvaluator,float类型的FloatEvaluator
这里直接看看FloatEvaluator的evaluate方法
————————————————
版权声明:本文为博主「google忠实粉丝」的原创文章
