android控件的动画分为三种:property animation,tween animation,frame animation,这三种动画模式在SDK中被称为property animation,view animation,drawable animation。



Ⅰ: View Animation(Tween Animation):


补间动画,给出两个关键帧,通过一些算法将给定属性值在给定的时间内在两个关键帧间渐变。
它只是改变了View对象的绘制,而没有改变View对象本身.

分为以下四种动画:

① AlphaAnimation



渐变动画,主要控制透明度变化动画类,常使用AlphaAnimation(float fromAlpha, float toAlpha)来构造;


fromAlpha:动画开始时的透明度(取值范围为0.0到1.0);
toAlpha:动画结束时的透明度;
duration:持续时间(单位:毫秒)

② ScaleAnimation

主要控制尺度变化的动画类,常使用ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)来构造;

fromX:动画开始X坐标上的伸缩尺度;
toX:动画结束X坐标上的伸缩尺度;
fromY:动画开始Y坐标上的伸缩尺度;
toY:动画结束Y坐标上的伸缩尺度;
pivotXType:X坐标上的伸缩模式,取值有:Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, Animation.RELATIVE_TO_PARENT;
pivotXValue:X坐标上的伸缩值;
pivotYType:Y坐标上的伸缩模式,取值有:Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, Animation.RELATIVE_TO_PARENT;
pivotYValue:Y坐标上的伸缩值;
duration:持续时间(单位:毫秒)

③ TranslateAnimation

主要控制位置变换的动画实现类,常使用TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)来构造;

fromXDelta:动画开始的X坐标;
toXDelta:动画结束的X坐标;
fromYDelta:动画开始的Y坐标;
toYDelta:动画结束的Y坐标;
duration:持续时间(单位:毫秒)

④ RotateAnimation

主要控制旋转的动画实现类,常使用RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)来构造;

fromDegrees:旋转开始角度;
toDegrees:旋转结束角度;
pivotXType, pivotXValue, pivotYType, pivotYValue与尺度变化动画ScaleAnimation类似;
duration:持续时间(单位:毫秒)

注意:

        在这些属性里面还可以加上%和p,例如:

        android:toXDelta="100%",表示自身的100%,也就是从View自己的位置开始。

        android:toXDelta="80%p",表示父层View的80%,是以它父层View为参照的。

        还可以是绝对的单位

2. 默认情况下,所有动画是同时进行的,可以通过startOffset属性设置各个动画的开始偏移(开始时间,单位:毫秒)来达到动画顺序播放的效果。

3. 可以通过设置interpolator属性改变动画渐变的方式,如AccelerateInterpolator,开始时慢,然后逐渐加快。默认为AccelerateDecelerateInterpolator。




定义好动画的XML文件后,可以通过类似下面的代码对指定View应用动画。


ImageView spaceshipImage = (ImageView)findViewById(R.id.spaceshipImage);
Animation hyperspaceJumpAnimation=AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);




Ⅱ: Drawable Animation(Frame Animation)


Drawable Animation(Frame Animation):帧动画,就像GIF图片,通过一系列Drawable依次显示来模拟动画的效果。通过给控件设置setBackgroundResource实现,在XML中的定义方式如下:


<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true"> //是否只播放一次
    <item android:drawable="@drawable/1" android:duration="200" />
    <item android:drawable="@drawable/2" android:duration="200" />
    <item android:drawable="@drawable/t3" android:duration="200" />
</animation-list>
//必须以<animation-list>为根元素,以<item>表示要轮换显示的图片,duration属性表示各项显示的时间。XML文件要放在/res/drawable/目录下

        imageView = (ImageView) findViewById(R.id.imageView);
        imageView.setBackgroundResource(R.drawable.drawable_anim);
        anim = (AnimationDrawable) imageView.getBackground();
	anim.start();

Ⅲ: Property Animation

属性动画,它更改的是对象的实际属性,在Tween Animation,其改变的是View的绘制效果,真正的View的属性保持不变,比如无论你在对话中如何缩放Button的大小,Button的有效点击区域还是没有应用动画时的区域,其位置与大小都不变。而在Property Animation中,改变的是对象的实际属性,如Button的缩放,Button的位置与大小属性值都改变了。而且Property Animation不止可以应用于View,还可以应用于任何对象。Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的.

在Property Animation中,可以对动画应用以下属性:
Duration:动画的持续时间
TimeInterpolation:插值器
TypeEvaluator:计算方式,根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值
Repeat Count and behavoir:重复次数与方式
Animation sets:动画集合,即可以同时对一个对象应用几个动画,这些动画可以同时播放也可以对不同动画设置不同开始偏移
Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响。

Property Animation的工作方式

ValueAnimator 表示一个动画,包含动画的开始值,结束值,持续时间等属性。
ValueAnimator封装了一个TimeInterpolator,TimeInterpolator定义了属性值在开始值与结束值之间的插值方法。
ValueAnimator还封装了一个TypeAnimator,根据开始、结束值与TimeIniterpolator计算得到的值计算出属性值。
ValueAnimator根据动画已进行的时间跟动画总时间(duration)的比计算出一个客观时间比例(0~1),然后根据TimeInterpolator计算出插值后的时间因子,最后TypeAnimator通过这个因子计算出属性值
对于ValueAnimator有两种监听

Animator.AnimatorListener(可通过继承AnimatorListenerAdapter简化操作,该抽象类为接口的空实现)
onAnimationStart()
onAnimationEnd()
onAnimationRepeat()
//当动画被取消时调用,同时会调用onAnimationEnd().
onAnimationCancel()

ValueAnimator.AnimatorUpdateListener

onAnimationUpdate()  //通过监听这个事件在属性的值更新时执行相应的操作,对于ValueAnimator一般要监听此事件执行相应的动作,不然Animation没意义,在ObjectAnimator(继承自ValueAnimator)中会自动更新属性,如无必要不必监听。在函数中会传递一个ValueAnimator参数,通过此参数的getAnimatedValue()取得当前动画属性值。

ObjectAnimator

继承自ValueAnimator,要指定一个对象及该对象的一个属性,当属性值计算完成时自动设置为该对象的相应属性,即完成了Property Animation的全部两步操作。实际应用中一般都会用ObjectAnimator来改变某一对象的某一属性,但用ObjectAnimator有一定的限制,要想使用ObjectAnimator,应该满足以下条件:
对象应该有一个setter函数:set(驼峰命名法)

1
2
3
4
5
6
7
8
9
10
tv=(TextView)findViewById(R.id.textview1);
btn=(Button)findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
    ObjectAnimator oa=ObjectAnimator.ofFloat(tv, "alpha", 0f, 1f);
    oa.setDuration(3000);
    oa.start();
  }
});
如上面的例子中,像ofFloat之类的工场方法,第一个参数为对象名,第二个为属性名,后面的参数为可变参数,如果values…参数只设置了一个值的话,那么会假定为目的值,属性值的变化范围为当前值到目的值,为了获得当前值,该对象要有相应属性的getter方法:get<PropertyName>
如果有getter方法,其应返回值类型应与相应的setter方法的参数类型一致。

如果上述条件不满足(即没有get方法和set方法),则不能用ObjectAnimator,应用ValueAnimator代替。根据应用动画的对象或属性的不同,可能需要在onAnimationUpdate函数中调用invalidate()函数刷新视图。

AnimationSet

AnimationSet提供了一个把多个动画组合成一个组合的机制,并可设置组中动画的时序关系,如同时播放,顺序播放等。

1
2
3
4
5
6
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(anim1).before(anim2);
bouncer.play(anim2).with(anim3);
bouncer.play(anim2).with(anim4)
bouncer.play(anim5).after(amin2);
animatorSet.start();

TypeEvalutors

根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值,android提供了以下几个evalutor:
IntEvaluator:属性的值类型为int;
FloatEvaluator:属性的值类型为float;
ArgbEvaluator:属性的值类型为十六进制颜色值;
TypeEvaluator:一个接口,可以通过实现该接口自定义Evaluator。
自定义TypeEvalutor很简单,只需要实现一个方法,如FloatEvalutor的定义:

1
2
3
4
5
6
public class FloatEvaluator implements TypeEvaluator {
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        float startFloat = ((Number) startValue).floatValue();
        return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
    }
}

TimeInterplator

AccelerateInterpolator          加速,开始时慢中间加速
DecelerateInterpolator         减速,开始时快然后减速
AccelerateDecelerateInterolator    先加速后减速,开始结束时慢,中间加速
AnticipateInterpolator        反向 ,先向相反方向改变一段再加速播放
AnticipateOvershootInterpolator    反向加回弹,先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值
BounceInterpolator         跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100
CycleIinterpolator         循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)
LinearInterpolator         线性,线性均匀改变
OvershottInterpolator        回弹,最后超出目的值然后缓慢改变到目的值
TimeInterpolator           一个接口,允许你自定义interpolator,以上几个都是实现了这个接口

LayoutTransition

Property animation系统还提供了对ViewGroup中的View改变加入动画的功能。当有子元素可见性改变时(VISIBLE、GONE),可以向其应用动画,通过LayoutTransition类应用此类动画:
container.setLayoutTransition(mTransitioner);
mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, customDisappearingAnim);
通过setAnimator应用动画,第一个参数表示应用的情境,可以以下4种类型:
APPEARING        当一个元素在其父元素中变为Visible时对这个元素应用动画
CHANGE_APPEARING    当一个元素在其父元素中变为Visible时,因系统要重新布局有一些元素需要移动,对这些要移动的元素应用动画
DISAPPEARING       当一个元素在其父元素中变为GONE时对其应用动画
CHANGE_DISAPPEARING  当一个元素在其父元素中变为GONE时,因系统要重新布局有一些元素需要移动,这些要移动的元素应用动画.
第二个参数为一Animator。
mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 30);
此函数设置动画延迟时间,参数分别为类型与时间。

Keyframes

keyFrame是一个 时间/值 对,通过它可以定义一个在特定时间的特定状态,即关键帧,而且在两个keyFrame之间可以定义不同的Interpolator,就好像多个动画的拼接,第一个动画的结束点是第二个动画的开始点。KeyFrame是抽象类,要通过ofInt(),ofFloat(),ofObject()获得适当的KeyFrame,然后通过PropertyValuesHolder.ofKeyframe获得PropertyValuesHolder对象,如以下例子:

1
2
3
4
5
6
7
8
Keyframe kf0 = Keyframe.ofInt(0, 400);
Keyframe kf1 = Keyframe.ofInt(0.25f, 200);
Keyframe kf2 = Keyframe.ofInt(0.5f, 400);
Keyframe kf4 = Keyframe.ofInt(0.75f, 100);
Keyframe kf3 = Keyframe.ofInt(1f, 500);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf4, kf3);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(btn2, pvhRotation);
rotationAnim.setDuration(2000);

上述代码的意思为:设置btn对象的width属性值使其:
开始时 Width=400
动画开始1/4时 Width=200
动画开始1/2时 Width=400
动画开始3/4时 Width=100
动画结束时 Width=500