动画分为三种:
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;
} |
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);
...
} |
最后是在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;
} |