Android 属性动画
属性动画框架
属性动画可以使用 ViewPropertyAnimator、ObjectAnimator、ValueAnimator 这三种 Animator。
它们其实是一种递进的关系:从左到右依次变得更加难用,也更加灵活。但它们的性能是一样的,因为 ViewPropertyAnimator 和 ObjectAnimator 的内部实现其实都是 ValueAnimator,ObjectAnimator 更是本来就是 ValueAnimator 的子类,它们三个的性能并没有差别。
它们的差别只是使用的便捷性以及功能的灵活性。所以在实际使用时候的选择,只要遵循一个原则就行:尽量用简单的。能用 View.animate() 实现就不用 ObjectAnimator,能用 ObjectAnimator 就不用 ValueAnimator。
属性动画要求动画作用的对象提供该属性的 set 方法,属性动画根据传递的该属性的初始值和最终值,以动画的效果多次去调用 set 方法。
每次传递给 set 方法的值都不一样,确切来说是随着时间的推移,所传递的值越来越接近最终值。
如果动画的时候没有传递初始值,那么还要提供 get 方法,因为系统要去获取属性的初始值。
工作原理可以总结为三步:
- 创建动画时,如果没有设置属性的初始值,此时 Android 系统会通过该属性的 get 方法获取初始值。(ObjectAnimator)
- 动画播放过程中,属性动画框架会利用时间流逝的百分比获取属性值改变的百分比(即通过时间插值器),接着利用获取的属性值改变的百分比获取改变后的属性值(即通过类型估值器)。(ObjectAnimator,ValueAnimator)
- 通过该属性的 set 方法将改变后的属性值设置到对象中,并将这种改变用动画得形式表现出来。(ObjectAnimator)
1 | FILE LOCATION: |
语法;
1 | <set |
View.animate() 示例
注:对应的 ViewPropertyAnimator 中的两个方法;
- 第一个:例如 translationX(100) 表示用动画把 View 的 translationX 值渐变为 100。
View会向右移动100像素。ViewPropertyAnimator不支持重复 - 第二个:例如 translationXBy(100) 表示用动画把 View 的 translationX 值渐变地增加 100。
View会向右移动100像素。如果再次执行动画,会从动画执行结束后的位置执行,再次向右移动100像素。
1 | /** |
ObjectAnimator 示例
为 ValueAnimator 的子类
因为属性的起始和结束值大多是在程序运行的时候动态获取的,所以推荐使用动态创建代码的方式。
1 | public class CustomSwitchingActivity extends AppCompatActivity implements View.OnClickListener { |
1 | /** |
常用的场景:
同一个动画中改变多个属性
区别于view.animate()的可以链式调用,对于 ObjectAnimator,可以使用 PropertyValuesHolder 来同时在一个动画中改变多个属性。
1 | PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("scaleX", 0,1); |
AnimatorSet 多个动画配合执行
如果在同一个动画中,会共享动画的开始时间、结束时间、Interpolator 等一系列的设定,这样就不能有先后次序地执行动画。
1 | ObjectAnimator animator4 = ObjectAnimator.ofFloat(ivHolder, "translationX", 0, -200); |
PropertyValuesHolders.ofKeyframe() 把同一个属性拆分
PropertyValuesHolder 通过设置 Keyframe(关键帧),把同一个动画属性拆分成多个阶段。
例如,你可以让一个进度增加到 100% 后再「反弹」回来。
1 | // 在 0% 处开始 |
ValueAnimator 示例
其实 ValueAnimator 类就是一个数值生成器,它只有上述工作原理的第二步,只要给ValueAnimator提供一个初始值、结束值和周期时间,ValueAnimator就会按照属性动画框架工作原理的第2步中的步骤生成具有一定规则的数字。
ValueAnimator 并不常用,因为它的功能太基础了。实际上,ValueAnimator 就是一个不能指定目标对象版本的 ObjectAnimator。
ObjectAnimator 是自动调用目标对象的 setter 方法来更新目标属性的值,以及很多的时候还会以此来改变目标对象的 UI。
而 ValueAnimator 只是通过渐变的方式来改变一个独立的数据,这个数据不是属于某个对象的,至于在数据更新后要做什么事,全都由你来定。
功能最少、最不方便,但有时也是束缚最少、最灵活。
比如有的时候,你要给一个第三方控件做动画,你需要更新的那个属性没有 setter 方法,只能直接修改,这个时候就可以用 ValueAnimator,在它的 onUpdate() 里面更新这个属性的值,并且手动调用 invalidate()。
1 | public class CustomSwitchingActivity extends AppCompatActivity { |
常用的场景
为 ViewGroup 的子 View 的显示和隐藏设置过渡动画
Android系统共提供了4种类型的过渡动画:
在layout文件中将ViewGroup的animateLayoutChanges属性打开就可以使用系统提供的默认过渡动画
自定义过渡动画示例:
1 | public class CustomSwitchingActivity extends AppCompatActivity { |
属性动画的监听器
主要两个接口:
- AnimatorUpdateListener:可监听动画的开始、结束、取消以及重复播放。、
- AnimatorListener:会监听整个动画过程,每播放一帧,会被调用一次。
备注
欢迎关注微信公众号:非也缘也