动画分为三种:

  • Tween Animation 补间动画
  • Drawable Animation帧动画
  • Property Animation 属性动画

补间动画

调用View.startAnimation(animation)开始动画

startAnimation

1
2
3
4
5
6
7
8
9
// 设置aniamtion的mStartTime一般是默认启动也就是-1
// 设置当前动画mCurrentAnimation = animation
// 标记mPrivateFlags 为PFLAG_INVALIDATED
// 最后调用invalidate 重新绘制
public void startAnimation(Animation animation) {
    setAnimation(animation);
    invalidateParentCaches();
    invalidate(true);
}

draw()

view在重绘制的时候会调用该方法

1
2
3
4
5
6
7
8
9
boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
       ... // 这里会先找到当前mCurrentAnimation是不是空
        final Animation a = getAnimation();
        if (a != null) {
            // 不是空的话调用applyLegacyAnimation方法
            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
           ...
        return more;
    }

### applyLegacyAnimation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
  private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
            Animation a, boolean scalingRequired) {
        Transformation invalidationTransform;
        final int flags = parent.mGroupFlags;
        final boolean initialized = a.isInitialized();
        if (!initialized) {// 如果动画还未初始化
            //对动画a进行reset 并设置a的mPreviousRegion
            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
            // 绑定回调handle
            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
            // 然后调用onstart
            onAnimationStart();
        }
        // 得到parent中的mChildTransformation
        final Transformation t = parent.getChildTransformation();
        // 这里是得到通过动画a对transformation进行改变
        boolean more = a.getTransformation(drawingTime, t, 1f);
        ...
        return more;
    }

Animation getTransformation

1
2
3
4
5
6
7
8
public boolean getTransformation(long currentTime, Transformation outTransformation) {
...

        // 根据mInterpolator计算interpolatedTime值,最后做出对应的操作
        final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
        applyTransformation(interpolatedTime, outTransformation);
...
}

Animation applyTransformation

最后是在applyTransformation方法中实现我们要操作的更改,如AlphaAnimation:

1
2
3
4
5
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
    final float alpha = mFromAlpha;
    t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
}

帧动画

一般用xml的处理比较多,要注意的是如果图片过大,引起OOM问题

1
2
3
4
5
6
<animation-list xmlns:android = "http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item android:drawable="@drawable/my1" android:duration="500" />
    <item android:drawable="@drawable/my2" android:duration="500" />
    <item android:drawable="@drawable/press" android:duration="500" />
</animation-list>   

### AnimationDrawable start

1
2
3
4
5
6
7
8
9
public void start() {
    // 标记为true
    mAnimating = true;
    if (!isRunning()) {
        // 调用setFrame方法
        setFrame(0, false, mAnimationState.getChildCount() > 1
                || !mAnimationState.mOneShot);
    }
}

### setFrame

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 private void setFrame(int frame, boolean unschedule, boolean animate) {
        // 如果当前选择的超过了一共的frame,就返回
        if (frame >= mAnimationState.getChildCount()) {
            return;
        }
        mAnimating = animate;
        mCurFrame = frame;
        // 把当前的drawable选为frame
        // 取得上一个drawable和当前drawble
        // 调用animate(true)
        // 根据每个frame设置的动画时间不一致,从而进行淡入淡出动画
        selectDrawable(frame);
        if (unschedule || animate) {
            // callback回调unscheduleSelf
            unscheduleSelf(this);
        }
        if (animate) {
            // Unscheduling may have clobbered these values; restore them
            mCurFrame = frame;
            mRunning = true;
            // callback回调scheduleSelf
            scheduleSelf(this, SystemClock.uptimeMillis() + mAnimationState.mDurations[frame]);
        }
    }

属性动画

目前用得比较多的,可以对任何对象做动画,针对ValueAnimator进行分析

start

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// 如果是playBackwards true 则回放,一般是false
private void start(boolean playBackwards) {
        对一些状态的判断,以及初始化属性
        ... 
        // 添加AnimationFrameCallback 会回调doAnimationFrame
        addAnimationCallback(0);
        if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
            // 调用startAnimation,并回调onAnimationStart
            startAnimation();
            // 如果当前的动画分数 是 -1
            if (mSeekFraction == -1) {
                //setCurrentPlayTime(0); 方法
                //则如果动画时间不是0,则设置当前次数(0)
                //否则则setCurrentFraction(1)当前次数为1
                setCurrentPlayTime(0);
            } else {
                // 设置setCurrentFraction(mSeekFraction)
                setCurrentFraction(mSeekFraction);
            }
        }
    }

setCurrentFraction

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public void setCurrentFraction(float fraction) {
    // 初始化动画的value属性
    initAnimation();
    // 计算动画分子 clampFraction
    // 如果是循环动画,则返回fraction
    // 不是则返回 Math.min(fraction, mRepeatCount + 1)
    fraction = clampFraction(fraction);
    mStartTimeCommitted = true; // 
    if (isPulsingInternal()) { // 如果不是第一次动画,上一次的mLastFrameTime >= 0
        // 重新计算mStartTime
        long seekTime = (long) (getScaledDuration() * fraction);
        long currentTime = AnimationUtils.currentAnimationTimeMillis();
        mStartTime = currentTime - seekTime;
    } else {
        // 修改mSeekFraction的值
        mSeekFraction = fraction;
    }
    mOverallFraction = fraction;
    final float currentIterationFraction = getCurrentIterationFraction(fraction, mReversing);
    // 通过mInterpolator重新计算fraction
    // mValues[i].calculateValue(fraction),重新计算值
    // 最后调用onAnimationUpdate
    animateValue(currentIterationFraction);
}

doAnimationFrame

每一帧会回调改方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public final boolean doAnimationFrame(long frameTime) {
       根据pause,resume等状态进行一些列操作
       ... 
       // 关键方法animateBasedOnTime判断是否完成动画
        boolean finished = animateBasedOnTime(currentTime);

        if (finished) {
            endAnimation();
        }
        return finished;
    }

animateBasedOnTime

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
boolean animateBasedOnTime(long currentTime) {
        boolean done = false;
        if (mRunning) { //如果是running
            // 动画时间
            final long scaledDuration = getScaledDuration();
            // 当前动画次数
            final float fraction = scaledDuration > 0 ?
                    (float)(currentTime - mStartTime) / scaledDuration : 1f;
            // 上一次的动画次数     
            final float lastFraction = mOverallFraction;
           // 当前的动画次数 是比 上一次的要大  
            final boolean newIteration = (int) fraction > (int) lastFraction;
            // 是否完成,不是循环动画,且动画分子大于了动画次数
            final boolean lastIterationFinished = (fraction >= mRepeatCount + 1) &&
                    (mRepeatCount != INFINITE);
            if (scaledDuration == 0) { 
                // 没有动画时间 直接返回true
                done = true;
            } else if (newIteration && !lastIterationFinished) {
                // 如果是新的,而且没有完成,则重新动画
                if (mListeners != null) {
                    int numListeners = mListeners.size();
                    for (int i = 0; i < numListeners; ++i) {
                        mListeners.get(i).onAnimationRepeat(this);
                    }
                }
            } else if (lastIterationFinished) {
                // 如果是完成了 也返回true
                done = true;
            }
            mOverallFraction = clampFraction(fraction);
            float currentIterationFraction = getCurrentIterationFraction(
                    mOverallFraction, mReversing);
                    // 更新动画
            animateValue(currentIterationFraction);
        }
        return done;
    }