Android 提供了很多丰富的 API 去实现动画效果,加上 SDK 25.3 时推出的 SpringAnimation,总共有三大类 Animation 供开发者使用。
View Animation
视图动画的作用对象是 View,可分为补间动画和帧动画。
补间动画
动画开始和结尾的中间过程都是假象,是渲染出来的表象,只是显示的位置变动,View的实际位置未改变,表现为View移动到其他地方,点击事件仍在原处才能响应。利用补间动画,同一个图形在界面上可以进行透明度(AlphaAnimation)、缩放(ScaleAnimation)、旋转(RotateAnimation)、平移(TranslateAnimation)的变化。
XML 方式
创建一个 set.xml 文件,通过动画集合标签
将四种效果结合起来
|
使用以上动画的方式如下
Animation anim = AnimationUtils.loadAnimation(context, R.anim.my_animation); |
Java 代码方式
使用 Java 代码实现动画的方式如下
public void startAnimationSet() { |
自定义
除了系统自带的四种补间动画,我们还可以自定义 View 动画。派生一种动画只需要继承抽象类 Animation,然后重写它的initialize
和applyTransformation
方法即可,在前一个方法中做初始化工作,后一个方法中进行相应的矩阵变换,本文不再详细介绍。
特殊使用
View 动画还可以用在控制 ViewGroup 中子元素的出场效果、实现不同 Activity 的切换效果等场景中。
帧动画
帧动画是顺序播放一组预先定义好的图片,类似于电影播放。不同于补间动画,系统提供了另外一个类 AnimationDrawable 来使用帧动画。
首先需要定义一个 XML 文件frame_animation.xml
|
然后将上述的 Drawable 作为 View 的背景并通过 Drawable 来播放动画即可
view.setBackgroundResource(R.drawable.frame_animation); |
Property Animation
属性动画在 API 11 引入,可以看作是增强版的补间动画,与补间动画的不同之处体现在:
- 补间动画只能定义两个关键帧在透明、旋转、位移和倾斜这四个属性的变换,但是属性动画可以定义任何属性的变化。
- 补间动画只能对 UI 组件执行动画,但属性动画可以对任何对象执行动画。
与补间动画类似,属性动画也需要定义几个方面的属性:
- 动画持续时间。默认为 300ms,可以通过 android:duration 属性指定。
- 动画插值方式。通过 android:interploator 指定。
- 动画重复次数。通过 android:repeatCount 指定。
- 重复行为。通过 android:repeatMode 指定。
- 动画集。在属性资源文件中通过
来组合。 - 帧刷新率。指定多长时间播放一帧。默认为 10 ms。
API
- ValueAnimator:属性动画用到的主要的时间引擎,负责计算各个帧的属性值。
- ObjectAnimator: ValueAnimator 的子类,对指定对象的属性执行动画。
- AnimatorSet:Animator 的子类,用于组合多个 Animator。
属性动画还提供了一个 Evaluator ,用来控制如何计算属性值。
- IntEvaluator:计算 int 类型属性值的计算器。
- FloatEvaluator:用于计算 float 类型属性值的计算器。
- ArgbEvaluator:用于计算十六进制形式表示的颜色值的计算器。
- TypeEvaluator:可以自定义计算器。
ValueAniamtor
ValueAnimator 类中有3个重要方法:
ValueAnimator.ofInt(int values)
ValueAnimator.ofFloat(float values)
ValueAnimator.ofObject(int values)
ofInt
将初始值以整型数值的形式过渡到结束值,即估值器是整型估值器 —— IntEvaluator
下面的代码将实现按钮的宽度从 150px 放大到 500px
Button mButton = (Button) findViewById(R.id.Button); |
ofFloat
其与 ofInt 的区别仅在于采用了浮点估值器(FloatEvaluator)
public class FloatEvaluator implements TypeEvaluator { |
ofObject
对于 ValueAnimator.ofInt 和 ValueAnimator.ofFloat 来说,由于使用了系统内置的估值器 —— FloatEvaluator 和 IntEvaluator,所以已经默认实现了从初始值到结束值的逻辑。
但对于 ValueAnimator.ofObject,并没有系统默认实现,因为对象的动画操作复杂多样,系统无法知道如何从初始对象过度到结束对象,因此需要自定义估值器(TypeEvaluator)来告知系统具体的逻辑。
自定义一个估值器 PointEvaluator,实现一个圆从一个点移动到另外一个点。默认已经有了一个点坐标类:Point,其具有 x 和 y 两个浮点属性。
public class PointEvaluator implements TypeEvaluator { |
将属性动画作用到自定义View当中
public class MyView extends View { |
ObjectAnimator
继承自 ValueAnimator 类,即底层的动画实现机制基于 ValueAnimator。
ObjectAnimator 与 ValueAnimator类的区别在于
- ValueAnimator 类是先改变值,然后手动赋值给对象的属性从而实现动画,属于间接对对象属性进行操作
- ObjectAnimator 类是先改变值,然后自动赋值给对象的属性从而实现动画,属于直接对对象属性进行操作
具体使用
对于
ObjectAnimator animator = ObjectAnimator.ofFloat(Object object, String property, float ….values);
其中 values 参数不定,表示动画初始值和结束值,如果是两个参数a,b,则动画效果是从属性的a值到b值;如果是三个参数a,b,c,则动画效果是从属性的a值到b值再到c值
对 Button 进行变换
|
自定义
在上面的例子中,我们给ObjectAnimator.ofFloat
的第二个参数String property
传入alpha
、rotation
、translationX
和scaleY
等值,实际上,我们可以传任意属性值,因为 ObjectAnimator 类实现动画效果的本质是:不断控制值的变化,再不断自动赋给对象的属性,赋值的过程是通过调用对象的get/set
方法进行的。
所以自定义属性就可以通过为对象设置需要操作属性的set/get
方法,再实现 TypeEvaluator 定义属性变化的逻辑完成。
还是对一个球做变换
public class MyView2 extends View { |
实现自定义估值器,完成颜色过渡的逻辑
public class ColorEvaluator implements TypeEvaluator { |
具体调用
ObjectAnimator anim = ObjectAnimator.ofObject(myView2, "color", new ColorEvaluator(), "#0000FF", "#FF0000"); |
此时还有一个问题需要我们解决:如果需要对 view 控件(比如 button)的宽高做变换,但是由于因为 View 中setWidth
并不是设置 View 的宽度,而是设置控件的最大和最小宽度,所以通过get/set
无法改变控件的宽度,也就无法实现动画效果。
解决方案是使用装饰器模式,包装原始动画对象,间接给对象加上该属性的get/set
方法。
ButtonWrapper wrapper = new ViewWrapper(button); |
AnimatorSet
最后介绍组合动画类,仅展示用法
|
Spring Animation
SpringAnimation,弹簧动画,位于android.support.animation
包中,属性动画位于android.animation.Animator
包中,其实通过 BounceInterpolator 或者 OvershootInterpolator 作为插值器,同样可以实现弹性动画效果,引入 SpringAnimation 是因为它使用更简单,而且上两个差值器实现的轨迹并不符合物理学上的弹跳效果。
使用之前需要导入com.android.support:support-dynamic-animation
包
API
public SpringAnimation(View v, ViewProperty property) |
参数分别是操作对应的View,对应的变化属性及最终的位置。
ViewProperty 包括(Z轴支持需要API >= 21):
TRANSLATION_X
TRANSLATION_Y
TRANSLATION_Z
SCALE_X
SCALE_Y
ROTATION
ROTATION_X
ROTATION_Y
X
Y
Z
ALPHA
SCROLL_X
SCROLL_Y
在 SpringAnimation 中有一个 SpringForce 对象,负责对应的变量设置及位置计算。其中包括两个个关键变量
- Stiffness 刚度(劲度/弹性),刚度越大,形变产生的里也就越大,体现在效果上就是运动越快
- DampingRatio 阻尼系数,系数越大,动画停止的越快。从理论上讲分为三种情况 Overdamped过阻尼(ζ > 1)、Critically damped临界阻尼(ζ = 1)、Underdamped欠阻尼状态(0 < ζ <1)。< li=""> 1)。<>
简单使用
SpringAnimation btnAnim = new SpringAnimation(mButton, SpringAnimation.TRANSLATION_Y, 0); |