一、animation 介绍
animation是Android应用中实现UI动画效果的途径,在Android应用中颇为常见。动画大体来说主要分为三种: 视图动画(View animation)、帧动画(frame animation)、属性动画(property animation)。本章主要介绍视图动画,而帧动画和属性动画将会在后面的章节中详细介绍。
二、视图动画 (view animation)
视图动画(view animation),指的是针对于view的动画效果。View动画分为四种,分别为 平移动画、缩放动画、旋转动画、透明度动画,也对应着Animation的四个子类: TranslateAnimation、 ScaleAnimation、 RotateAnimation、 AlphaAnimation。
动画名称 | XML标签 | 类名 | 动画效果 |
---|---|---|---|
平移动画 | <translate> | TranslateAnimation | 使View平移 |
旋转动画 | <rotate> | RotateAnimation | 使View旋转 |
缩放动画 | <scale> | ScaleAnimation | 使View放大或缩小 |
透明度动画 | <alpha> | AlphaAnimation | 使View透明度改变 |
View动画可以使用XML来创建,也可以通过java代码创建。
使用XML创建View动画,首先需要在路径 res/anim/ 下创建一个xml文件,然后在文件中添加固定的描述语法,如下:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="200"
android:toYDelta="200"
android:fillAfter="true"
/>
<rotate
android:duration="500"
android:fromDegrees="360"
android:toDegrees="0"
android:pivotX="0"
android:pivotY="0"
android:fillAfter="true"
/>
</set>
然后在java代码中载入:
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.translate_animation);
imageView.startAnimation(animation);
即可开始动画。
在java代码中,也可以直接设置动画。如下
AnimationSet animationSet = new AnimationSet(false);
AlphaAnimation alphaAnimation = new AlphaAnimation(
GlobalAnimation.Alpha.fromAlpha,
GlobalAnimation.Alpha.toAlpha);
RotateAnimation rotateAnimation = new RotateAnimation(
GlobalAnimation.Rotate.fromDegrees,
GlobalAnimation.Rotate.toDegrees,
GlobalAnimation.Rotate.pivotX,
GlobalAnimation.Rotate.pivotY);
ScaleAnimation scaleAnimation = new ScaleAnimation(
GlobalAnimation.Scale.fromXScale,
GlobalAnimation.Scale.toXScale,
GlobalAnimation.Scale.fromYScale,
GlobalAnimation.Scale.toYScale,
GlobalAnimation.Scale.pivotX,
GlobalAnimation.Scale.pivotY);
TranslateAnimation translateAnimation = new TranslateAnimation(
GlobalAnimation.Translate.fromDeltaX,
GlobalAnimation.Translate.toDeltaX,
GlobalAnimation.Translate.fromDeltaY,
GlobalAnimation.Translate.toDeltaY);
animationSet.addAnimation(translateAnimation);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.setDuration(2000);
imageView.startAnimation(animationSet);在逐个了解动画之前,有三个共同的属性需要知道:
duration: The duration of one animation cycle in milliseconds. 动画一个循环需要进行的时间,单位是毫秒
fillbefore: Indicates whether the animation transformation should be applied before the animation starts. The value of this variable is only relevant if mFillEnabled is true; otherwise it is assumed to be true. 是否在动画开始之前,转换view。即当为false时,动画开始之前,view会恢复原位,反之则不会。
fillAfter: Indicates whether the animation transformation should be applied after the animation ends. 是否在动画结束后转换view。即为false时,在动画结束之后,view会恢复原位,反之则不会。
2.1 translate animation
translate animation 即位移动画,其常用的属性如下
- fromXDelta: 表示view在x坐标上的起始相对位置。
- fromYDelta: 表示view在y坐标上的起始相对位置。
- toXDelta: 表示view在x坐标上的结束相对位置。
- toYDelta: 表示view在y坐标上的结束相对位置。
下面,让我们通过实际操作来直观地分析 translateAnimation的特点。
我们从上面的三幅图中可以看出,以view的位置为坐标系原点,在位移动画中,有三个重要的点 原点 O(0,0) 动画起始点 F(fromXDelta, fromYDelta) 动画结束点 T(toXDelta, toYDelta)。
从第一幅动态图中,可以看出,当fillBefore和fillAfter都未勾选时,view在动画开始前,和动画结束后,都停留在原点O,在动画开始后,会瞬间闪至点F,然后根据duration的设置的时间,移动到T点上。
从第二幅动态图中,可以看出,当fillBefore为false,fillAfter为true时,view在动画结束后,并未回到原点O,而是停留在了结束点T上,还有一个很重要的细节,就是在动画开始时,view会先闪回原点O,在闪至动画开始点F。
从第三幅动态图中,可以看出,当fillBefore和fillAfter均为true时,view在动画结束后,停留在结束点T,在动画重新开始时,也并不会回到原点O,而是直接闪到了起始点F。
从这三幅图中已经可以明显地看出fillBefore和fillAfter的作用,后面其他动画的介绍将不会再针对这两个成员变量多作分析。
2.2 scale animation
ScaleAnimation 即缩放动画,其常用属性如下:
- fromXScale: view在x坐标上缩放的起始值。
- fromYScale: view在y坐标上缩放的起始值。
- toXScale: view在x坐标上缩放的结束值。
- toYScale: view在Y坐标上缩放的结束值。
- pivotX: view缩放的中心轴点的x坐标。
- pivotY: view缩放的中心轴点的y坐标。
下面,让我们通过实际操作来直观地分析 ScaleAnimation的特点。
从图示可以看出动画开始时,view会瞬间缩放至fromscale设置的大小,然后在duration的时间内,缩放至toscale设置的大小。
而pivot则是设置缩放的中心点,具体效果如图示。以左上角为起始点偏移,pivot默认是使用绝对偏移量,如设置100,则中心偏移100px,当然,还有多种偏移模式,可以通过设置pivotType切换偏移模式,来我们可以在ScaleAnimation的源码中看到:
switch (type) {
case ABSOLUTE:
return value;
case RELATIVE_TO_SELF:
return size * value;
case RELATIVE_TO_PARENT:
return parentSize * value;
default:
return value;
}
默认是使用absolute模式,即直接使用px作为偏移。当设置为relative_to_self是,值应在0%-100%中,即已自身位置的百分比作为中心轴点的偏移。当设置为relative_to_parent时,值应在0%-100%中,即已父布局的百分比作为中心轴点的偏移。
2.3 rotate animation
- rotate animation 即旋转动画,让我们来看下其常用属性:
- fromDegrees: view开始旋转的角度。
- toDegrees: view结束旋转的角度。
- pivotX: view旋转的中心轴点的x坐标。
- pivotY: view旋转的中心轴点的y坐标。
下面,让我们通过实际操作来直观地分析 RotateAnimation的特点。
RotateAnimation很好理解,从一个角度旋转到另一个角度,若起始角度小于结束角度,则顺时针旋转,否则逆时针旋转。
而RotateAnimation的pivot和ScaleAnimation的pivot是相同的,这里就不再赘述。
2.4 alpha animation
alpha animation 即透明度动画,让我们来看下其常用属性:
- fromAlpha: view透明度的起始值。
- toAlpha: view透明度的结束值。
下面,让我们通过实际操作来直观的分析 AlphaAnimation的特点:
透明度动画也很容易理解,就是view的透明度从fromAlpha 在 duration 时间内变化至toAlpha。
2.5 animation set
animation set即动画集合。
动画效果不是单一的,可以通过AnimationSet来使动画叠加,实现一些负责的动画效果。
从第一幅动态图中,可以看出,AnimationSet动画集合内的动画,都是同步播放,我们设置了位移动画为两秒,其他的动画时间在一秒左右,而我们在动画中很明显可以看到,在最后有一段单独的位移动画,因此可以看出在AnimationSet未设置duration时,set内的动画是各自计算时间的。
从第二幅动态图中,可以看出,当AnimationSet未设置fillBefore和fillAfter时,即使set内的动画,全都设置了fillBefore和fillAfter也不会生效。
从第三幅动态图中,可以看出,当AnimationSet设置了duration时,每个动画的时间都变成了set的duration,效果相当于将set内的每个动画的duration都设置成AnimationSet的duration。另外可以看到,当设置了AnimationSet的fillBefore和fillAfter时,动画停在了最后一帧。
2.6 Interpolator 插值器
在上面的动态图中,我们可以发现一个现象,动画都有一个加速和减速过程,即两头慢中间快。那么我们可不可以让动画只加速,只减速,或者一直匀速播放呢?当然是可以的,这就是 Interpolator插值器的作用了。
view动画的本质其实也是一帧一帧显示的,假设动画过程中需要改变的x,y的量为1,总时间为1,那么当时间流逝0.1时,x,y需要改变多少,这个时候,就会通过估值器根据设置的插值器去计算。
默认设置的插值器是AccelerateDecelerateInterpolator(即加速减速插值器),除此之外,还有LinearInterpolator(线性插值器:匀速插值器)、AccelerateInterpolator(加速插值器)、DecelerateInterpolator(减速插值器)。
那么AnimationSet的插值器,和set中单个动画的插值器的关系是什么呢? 在AnimationSet中,有一个boolean成员变量叫 shareInterpolator,通过设置该成员变量,来设置集合中的动画,是否和集合共用一个插值器。