补间动画详解一 基类Animation

本文深入探讨了Android中的补间动画,重点介绍了Animation基类及其子类AlphaAnimation、RotateAnimation、ScaleAnimation和TranslateAnimation。同时,提到了组合动画的AnimationSet类,并给出了官方文档链接和类图概述。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

补间动画(Tween animation)是通过在两个关键帧之间补充渐变的动画效果来实现的。

Android系统提供了四个补间动画的类,分别是AlphaAnimationRotateAnimationScaleAnimationTranslateAnimation,另外还有一个能够把多个动画组合起来的AnimationSet类,这些类都有一个共同的基类Animation。

Animation类官方文档:
https://developer.android.com/reference/android/view/animation/Animation.html

类图:


一、Animation介绍

Animation是一个抽象类,无法直接使用,通常使用的是它的直接子类。

public abstract class Animation implements Cloneable {
}

Animation类定义了一些与动画相关的变量,子类可以直接使用。
/**
 * 一个动画周期的持续时间,以毫秒为单位。
 */
long mDuration;

/**
 * 动画开始执行的延时时长。如果大于0,动画的执行时间为startTime+startOffset。
 */
long mStartOffset;

/**
 * 设置为true时,将保持动画开始前的状态。默认值为true。
 */
boolean mFillBefore = true;

/**
 * 设置为true时,将保持动画结束时的状态。默认值为false。
 */
boolean mFillAfter = false;

/**
 * 设置为true时,将应用mFillBefore的值;否则,忽视mFillBefore的值。默认值为false。
 */
boolean mFillEnabled = false;

/**
 * 动画重复的次数。
 */
int mRepeatCount = 0;

/**
 * 动画的重复类型,取值为RESTART(从头播放)或REVERSE(倒序回放)。
 */
int mRepeatMode = RESTART;

/**
 * 表示动画在执行期间,被设置动画的内容在Z轴上的顺序。
 * 取值范围ZORDER_NORMAL(保持不动)、ZORDER_TOP(在所有其他内容的顶部)、ZORDER_BOTTOM(在所有其他内容的底部),默认为ZORDER_NORMAL
 */
private int mZAdjustment;

/**
 * 动画的背景色。
 */
private int mBackgroundColor;

/**
 * 如果设置为true,并且动画窗体有一个壁纸的话,那么动画只会应用给窗体,壁纸是静止不动的。默认值为false。
 */
private boolean mDetachWallpaper = false;

/**
 * 插值器,用来修饰动画效果。
 */
Interpolator mInterpolator;

同时也有一些常量,用来给特定的变量赋值。
/**
 * mRepeatCount设置为INFINITE,表示动画无限循环。
 */
public static final int INFINITE = -1;

/**
 * mRepeatMode设置为RESTART,表示动画结束后从头开始执行。
 */
public static final int RESTART = 1;

/**
 * mRepeatMode设置为REVERSE,表示动画结束后反过来执行。
 */
public static final int REVERSE = 2;

/**
 * setStartTime()传入该值时,动画将在第一次调用getTransformation(long, Transformation)时开始执行。
 */
public static final int START_ON_FIRST_FRAME = -1;

/**
 * 具体的坐标值。
 */
public static final int ABSOLUTE = 0;

/**
 * 相对自身的坐标值。
 */
public static final int RELATIVE_TO_SELF = 1;

/**
 * 相对父容器的坐标值。
 */
public static final int RELATIVE_TO_PARENT = 2;

/**
 * mZAdjustment设置为ZORDER_NORMAL,表示内容在Z轴保持不动。
 */
public static final int ZORDER_NORMAL = 0;

/**
 * mZAdjustment设置为ZORDER_TOP,表示内容的Z轴方向在所有其他内容的顶部。
 */
public static final int ZORDER_TOP = 1;

/**
 * mZAdjustment设置为ZORDER_BOTTOM,表示内容的Z轴方向在所有其他内容的底部。
 */
public static final int ZORDER_BOTTOM = -1;

这些成员变量在构造方法中被初始化。
public Animation(Context context, AttributeSet attrs) {
    TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Animation);

    setDuration((long) a.getInt(com.android.internal.R.styleable.Animation_duration, 0));
    setStartOffset((long) a.getInt(com.android.internal.R.styleable.Animation_startOffset, 0));

    setFillEnabled(a.getBoolean(com.android.internal.R.styleable.Animation_fillEnabled, mFillEnabled));
    setFillBefore(a.getBoolean(com.android.internal.R.styleable.Animation_fillBefore, mFillBefore));
    setFillAfter(a.getBoolean(com.android.internal.R.styleable.Animation_fillAfter, mFillAfter));

    setRepeatCount(a.getInt(com.android.internal.R.styleable.Animation_repeatCount, mRepeatCount));
    setRepeatMode(a.getInt(com.android.internal.R.styleable.Animation_repeatMode, RESTART));

    setZAdjustment(a.getInt(com.android.internal.R.styleable.Animation_zAdjustment, ZORDER_NORMAL));

    setBackgroundColor(a.getInt(com.android.internal.R.styleable.Animation_background, 0));

    setDetachWallpaper(a.getBoolean(com.android.internal.R.styleable.Animation_detachWallpaper, false));

    final int resID = a.getResourceId(com.android.internal.R.styleable.Animation_interpolator, 0);

    a.recycle();

    if (resID > 0) {
        setInterpolator(context, resID);
    }

    ensureInterpolator();
}
上面的每一个成员变量都有与之对应的set方法和xml属性。以成员变量mDuration为例,它的set方法为setDuration(),xml属性为android:duration。

Animation类内部定义了动画的监听器AnimationListener,通过调用setAnimationListener()方法来设置监听器。

AnimationListener mListener;

/**
 * 设置动画的监听
 */
public void setAnimationListener(AnimationListener listener) {
    mListener = listener;
}

/**
 * 动画的监听
 */
public static interface AnimationListener {
    /**
     * 动画开始时回调。
     */
    void onAnimationStart(Animation animation);

    /**
     * 动画结束时回调。
     * 但是当动画重复次数被设置为INFINITE的时候,该方法不会回调。
     */
    void onAnimationEnd(Animation animation);

    /**
     * 动画重复时回调。
     */
    void onAnimationRepeat(Animation animation);
}

Animation类是通过applyTransformation()方法来处理动画变化的过程。
protected void applyTransformation(float interpolatedTime, Transformation t) {
}
可以看到,在Animation类中applyTransformation()方法是空的,具体实现由它的四个子类来完成。每个动画实现类都重载了Animation类的applyTransformation()方法,该方法把一些属性组装成一个Transformation类,该方法会被getTransformation()方法调用。
在动画的执行过程中,会反复的调用applyTransformation()方法。每次调用参数interpolatedTime值都会变化,该参数从0.0递增为1.0,当该参数为1.0时表示动画结束。Transformation类封装了矩阵Matrix和透明度Alpha值,通过参数Transformation来设置Matrix和Alpha,实现各种效果。

如果我们需要实现自己的动画类,需要下面两个步骤:
(1).继承Animation类。
(2).实现applyTransformation()方法。


一、Animation执行过程

在启动动画时,一般是调用View类的startAnimation(anim)方法。
先从View类开始看起。

public void startAnimation(Animation animation) {
    animation.setStartTime(Animation.START_ON_FIRST_FRAME);
    setAnimation(animation);
    invalidateParentCaches();
    invalidate(true);
}

protected Animation mCurrentAnimation = null;

public void setAnimation(Animation animation) {
    mCurrentAnimation = animation;
    // other code ......
}
在startAnimation()方法内部,先调用setAnimation()方法给成员变量mCurrentAnimation赋值,然后它调用invalidate()来重绘自己。

接下来进入draw()方法。
boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
    // other code ......
    final Animation a = getAnimation();
    if (a != null) {
        more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
    }
    // other code ......
}

public Animation getAnimation() {
    return mCurrentAnimation;
}

private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
            Animation a, boolean scalingRequired) {
    // other code ......
    boolean more = a.getTransformation(drawingTime, t, 1f);
    // other code ......
}
在draw()方法内部调用了View类的applyLegacyAnimation(),而applyLegacyAnimation()内部又调用了Animation类的getTransformation(long,Transformation,float)方法。

再次回到Animation类中,会发现最终在getTransformation()方法中调用了applyTransformation()方法,实现各种动画效果。
public boolean getTransformation(long currentTime, Transformation outTransformation,
    float scale) {
    mScaleFactor = scale;
    return getTransformation(currentTime, outTransformation);
}

public boolean getTransformation(long currentTime, Transformation outTransformation) {
    // other code ......
    applyTransformation(interpolatedTime, outTransformation);
    // other code ......
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值