Animator属性动画源码
仔细看看属性动画的源码,加深对动画实现原理的了解。ObjectAnimator继承自ValueAnimator,本篇主要以ValueAnimator为主。关于属性动画,详见之前两篇介绍属性动画的文章:属性动画:ValueAnimator和属性动画:ObjectAnimator。
1、属性动画的构造
得益于框架优秀的设计,构造一个属性动画对象很简单,举个简单的例子:
//ValueAnimator动画
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100);
//ObjectAnimator动画
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "alpha", 0, 1);从ValueAnimator的ofInt()方法开始,使用该方法可以获得一个ValueAnimator实例:
public static ValueAnimator ofInt(int... values) {
ValueAnimator anim = new ValueAnimator();
anim.setIntValues(values);
return anim;
}ofInt()方法中先用ValueAnimator默认构造函数直接构造一个实例;再调用setIntValues(values)方法设置初始化,其中主要涉及PropertyValuesHolder、Keyframes等属性创建。
public void setIntValues(int... values) {
if (values == null || values.length == 0) {
return;
}
//是否已经设置过PropertyValuesHolder属性
if (mValues == null || mValues.length == 0) {
//创建PropertyValuesHolder,并添加到当前ValueAnimator属性动画中。
setValues(PropertyValuesHolder.ofInt("", values));
} else {
//直接更新已有的PropertyValuesHolder属性值
PropertyValuesHolder valuesHolder = mValues[0];
valuesHolder.setIntValues(values);
}
// New property/values/target should cause re-initialization prior to starting
mInitialized = false;
}创建特定的PropertyValuesHolder对象并添加到当前ValueAnimator属性动画中。
public static PropertyValuesHolder ofInt(String propertyName, int... values) {
//这里为int类型,创建返回IntPropertyValuesHolder
return new IntPropertyValuesHolder(propertyName, values);
}在IntPropertyValuesHolder的构造方法中设置关键帧,使用PropertyValuesHolder的setIntValues(int... values)方法:
public void setIntValues(int... values) {
mValueType = int.class;
//调用KeyframeSet的ofInt方法,创建关键帧集合
mKeyframes = KeyframeSet.ofInt(values);
}随后又会使用Keyframe创建关键帧,并添加到关键帧集合KeyframeSet中:
public static KeyframeSet ofInt(int... values) {
int numKeyframes = values.length;
IntKeyframe keyframes[] = new IntKeyframe[Math.max(numKeyframes,2)];
if (numKeyframes == 1) {
keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f);
keyframes[1] = (IntKeyframe) Keyframe.ofInt(1f, values[0]);
} else {
keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f, values[0]);
for (int i = 1; i < numKeyframes; ++i) {
keyframes[i] =
(IntKeyframe) Keyframe.ofInt((float) i / (numKeyframes - 1), values[i]);
}
}
//同样,参数为int,返回的是IntKeyframeSet。此外,还有FloatKeyframeSet、KeyframeSet
return new IntKeyframeSet(keyframes);
}源码的分支逻辑很多,阅读源码的时候只需要关注主要流程。手动画时序图费时间,直接用SequenceDiagram基于API 31的源码,生成了创建ValueAnimator属性动画的时序图,如下:
类似的,创建ObjectAnimator的时序图:
2、属性动画的执行
拿到属性动画对象后,再设置插值器、监听器、动画时长等属性,就可以播放动画。
//设置插值器,默认为AccelerateDecelerateInterpolator。如果设置为null,则使用LinearInterpolator
valueAnimator.setInterpolator(new AnticipateInterpolator());
//设置动画时长,默认300ms
valueAnimator.setDuration(500);
//ValueAnimator动画的使用就是监听值的变化,自行设置动画值。
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float val = (float) animation.getAnimatedValue();
//TODO(use val)
}
});
//开启动画,在UI线程 或者 带Looper的子线程也可
valueAnimator.start();2.1、播放动画
从start()方法为入口,开始阅读源码。如果用reverse()开始动画,动画则是反向播放。
public void start() {
//正向播放动画,而不是反向播放动画。
start(false);
}接着调用start(boolean playBackwards)。这里虽然没有强制一定要在主线程才能播放动画,但是要求所在线程必须拥有Looper。动画将在调用线程上运行,如果在动画过程中更新View的属性,显然,这需要在UI线程才能进行操作。
private void start(boolean playBackwards) {
//必须在有Looper的线程调用,虽然这里没有强制UI线程,
if (Looper.myLooper() == null) {
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
}
...
//一系列动画相关的状态设置
mStarted = true;
mPaused = false;
mRunning = false;
mAnimationEndRequested = false;
...
//真正触发动画的方法在这里
addAnimationCallback(0);
if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
// 通知监听器等待动画开始
startAnimation();
...
}
}在start(boolean playBackwards)方法中调用到两个关键方法:一个是addAnimationCallback(long delay),另一个是startAnimation()。从方法名看,会误以为startAnimation()是开启动画的方法,其实addAnimationCallback(long delay)方法才是:
private void addAnimationCallback(long delay) {
if (!mSelfPulse) {
return;
}
getAnimationHandler().addAnimationFrameCallback(this, delay);
}AnimationHandler类,顾名思义,进行动画处理。
public AnimationHandler getAnimationHandler() {
return mAnimationHandler != null ? mAnimationHandler : AnimationHandler.getInstance();
}借助ThreadLocal,执行动画所在的线程(而不是创建线程)可以拿到唯一的一个AnimationHandler实例,用来处理当前线程中的所有动画。
public final static ThreadLocal<AnimationHandler> sAnimatorHandler = new ThreadLocal<>();
public static AnimationHandler getInstance() {
if (sAnimatorHandler.get() == null) {
sAnimatorHandler.set(new AnimationHandler());
}
return sAnimatorHandler.get();
}调用AnimationHandler的addAnimationFrameCallback(AnimationFrameCallback , delay)方法先注册一个Choreographer.FrameCallback回调给Choreographer,再将ValueAnimator注册到AnimationHandler中。
public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
if (mAnimationCallbacks.size() == 0) {
//将AnimationHandler中的mFrameCallback回调注册给Choreographer
getProvider().postFrameCallback(mFrameCallback);
}
if (!mAnimationCallbacks.contains(callback)) {
//将Animator属性动画实例注册到AnimationHandler
mAnimationCallbacks.add(callback);
}
...
}AnimationHandler中的MyFrameCallbackProvider内部类实现AnimationFrameCallbackProvider接口,其中有一个Choreographer实例,Choreographer不是本篇重点,关于Choreographer详见Choreographer源码阅读一文。
/**
* Default provider of timing pulse that uses Choreographer for frame callbacks.
*/
private class MyFrameCallbackProvider implements AnimationFrameCallbackProvider {
//Choreographer实例
final Choreographer mChoreographer = Choreographer.getInstance();
//注册Callback到Choreographer中
@Override
public void postFrameCallback(Choreographer.FrameCallback callback) {
mChoreographer.postFrameCallback(callback);
}
@Override
public void postCommitCallback(Runnable runnable) {
mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT, runnable, null);
}
@Override
public long getFrameTime() {
return mChoreographer.getFrameTime();
}
@Override
public long getFrameDelay() {
return Choreographer.getFrameDelay();
}
@Override
public void setFrameDelay(long delay) {
Choreographer.setFrameDelay(delay);
}
}mFrameCallback是定义在AnimationHandler类中的Choreographer.FrameCallback回调。
private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
doAnimationFrame(getProvider().getFrameTime());
if (mAnimationCallbacks.size() > 0) {
getProvider().postFrameCallback(this);
}
}
};在addAnimationFrameCallback(AnimationFrameCallback , delay)方法中被注册给Choreographer。
public void postFrameCallback(FrameCallback callback) {
postFrameCallbackDelayed(callback, 0);
}经过几个方法的调用传递,从postFrameCallbackDelayed(FrameCallback ,delayMillis)方法:
public void postFrameCallbackDelayed(FrameCallback callback, long delayMillis) {
if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
}
postCallbackDelayedInternal(CALLBACK_ANIMATION,callback, FRAME_CALLBACK_TOKEN, delayMillis);
}再到postCallbackDelayedInternal()方法:
private void postCallbackDelayedInternal(int callbackType,
Object action, Object token, long delayMillis) {
...
synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
//这里的action就是传入的mFrameCallback
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
if (dueTime <= now) {
scheduleFrameLocked(now);
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}scheduleFrameLocked(long now)方法中检查是否启用USE_VSYNC,如果没有就用消息机制刷新。
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
//检查是否启用USE_VSYNC,默认为true
if (USE_VSYNC) {
...
//在Looper线程上执行
if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
//如果没有启用USE_VSYNC,则通过异步消息执行屏幕刷新
final long nextFrameTime = Math.max(
mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
}
Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextFrameTime);
}
}
}Choreographer中的USE_VSYNC属性默认为true,为动画和绘图启用垂直同步。
// Enable/disable vsync for animations and drawing.
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769497)
private static final boolean USE_VSYNC = SystemProperties.getBoolean(
"debug.choreographer.vsync", true);最终执行scheduleVsyncLocked()请求底层VSYNC信号:
private void scheduleVsyncLocked() {
mDisplayEventReceiver.scheduleVsync();
}mDisplayEventReceiver为FrameDisplayEventReceiver实例,FrameDisplayEventReceiver继承自DisplayEventReceiver,用于接收同步脉冲信号VSYNC,在Choreographer构造方法中初始化:
private Choreographer(Looper looper, int vsyncSource) {
mLooper = looper;
mHandler = new FrameHandler(looper);
mDisplayEventReceiver = USE_VSYNC
? new FrameDisplayEventReceiver(looper, vsyncSource) : null;
...
}在DisplayEventReceiver的scheduleVsync()方法中,又调用了Native方法nativeScheduleVsync(long receiverPtr),向SurfaceFlinger服务注册,请求系统发送脉冲信号开启动画。
public void scheduleVsync() {
nativeScheduleVsync(mReceiverPtr);
}Native层处理完会回调DisplayEventReceiver的dispatchVsync()函数,至于底层如何处理,这里就不往下卷了。
跟随源码看到这里,将属性动画ValueAnimator启动的主要流程走了一遍。简化的时序图如下:
ObjectAnimator继承自ValueAnimator,开启动画流程和ValueAnimator类似,只是在start()中多了一个AnimationHandler的autoCancelBasedOn(ObjectAnimator )方法调用:
2.2、动画执行
Native收到VSYNC同步脉冲信号,就会回调DisplayEventReceiver的dispatchVsync()方法,类似发布订阅模式。
// Called from native code.
private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame,
long frameTimelineVsyncId, long frameDeadline, long frameInterval) {
onVsync(timestampNanos, physicalDisplayId, frame,
new VsyncEventData(frameTimelineVsyncId, frameDeadline, frameInterval));
}FrameDisplayEventReceiver继承自DisplayEventReceiver,重写了DisplayEventReceiver中的onVsync()空方法。在该方法中向FrameHandler发送消息,
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
...
@Override
public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
VsyncEventData vsyncEventData) {
...
//创建发送的消息,虽然没有指明what或者其它标志,但是Callback传递的是自身
//因为FrameDisplayEventReceiver本身继承自Runnable
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
//向FrameHandler发送消息
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
...
}
@Override
public void run() {
mHavePendingVsync = false;
//最后Handler处理上面onVsync()发送的消息时,会执行该方法。
doFrame(mTimestampNanos, mFrame, mLastVsyncEventData);
}
}由于发送的Message中指明callback为FrameDisplayEventReceiver本身,所以会执行run()方法,另见Handler中Callback的作用一文。进而执行Choreographer中的doFrame()方法:
void doFrame(long frameTimeNanos, int frame,
DisplayEventReceiver.VsyncEventData vsyncEventData) {
...
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos, frameIntervalNanos);
mFrameInfo.markAnimationsStart();
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos, frameIntervalNanos);
doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos,
frameIntervalNanos);
mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos, frameIntervalNanos);
doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos, frameIntervalNanos);
...
}动画对应执行的Callback类型是CALLBACK_ANIMATION:
/**
* Callback type: Animation callback. Runs before {@link #CALLBACK_INSETS_ANIMATION}.
* @hide
*/
@TestApi
public static final int CALLBACK_ANIMATION = 1;紧接着调用doCallbacks(...)方法,该方法比较长,看源码就得选择性忽略,真正有用的浓缩成下面几行:
void doCallbacks(int callbackType, long frameTimeNanos, long frameIntervalNanos) {
CallbackRecord callbacks;
...
callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(
now / TimeUtils.NANOS_PER_MS);
...
for (CallbackRecord c = callbacks; c != null; c = c.next) {
c.run(frameTimeNanos);
}
...
}还记得Choreographer中的mCallbackQueues[]吗?在前面开启动画的过程中就使用postCallbackDelayedInternal(...)将AnimationHandler中的Choreographer.FrameCallback回调mFrameCallback注册到mCallbackQueues[CALLBACK_ANIMATION]里。
从mCallbackQueues[CALLBACK_ANIMATION]中拿到CallbackRecord对象,执行其run()方法:
private static final class CallbackRecord {
...
public Object action; // Runnable or FrameCallback
...
public void run(long frameTimeNanos) {
if (token == FRAME_CALLBACK_TOKEN) {
((FrameCallback)action).doFrame(frameTimeNanos);
} else {
((Runnable)action).run();
}
}
}CallbackRecord中的action就是AnimationHandler中的mFrameCallback回调对象。这里注意,如果还有动画回调对象注册,也就是动画没有执行完,会继续请求下一个VSYNC信号,从而稳定的进行动画。
private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
doAnimationFrame(getProvider().getFrameTime());
if (mAnimationCallbacks.size() > 0) {
getProvider().postFrameCallback(this);
}
}
};在Choreographer.FrameCallback回调执行AnimationHandler的doAnimationFrame(long frameTime)方法
private void doAnimationFrame(long frameTime) {
...
for (int i = 0; i < size; i++) {
final AnimationFrameCallback callback = mAnimationCallbacks.get(i);
...
callback.doAnimationFrame(frameTime);
...
}
cleanUpList();
}mAnimationCallbacks很眼熟,就是前面开始播放ValueAnimator动画的时候,通过addAnimationCallback(long delay)方法:
private void addAnimationCallback(long delay) {
if (!mSelfPulse) {
return;
}
getAnimationHandler().addAnimationFrameCallback(this, delay);
}将属性动画ValueAnimator注册添加到AnimationHandler的中,存在mAnimationCallbacks集合里:
/**
* Register to get a callback on the next frame after the delay.
*/
public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
//将AnimationHandler中的mFrameCallback注册给Choreographer
if (mAnimationCallbacks.size() == 0) {
getProvider().postFrameCallback(mFrameCallback);
}
//将ValueAnimator添加到动画回调集合中
if (!mAnimationCallbacks.contains(callback)) {
mAnimationCallbacks.add(callback);
}
...
}ValueAnimator实现了AnimationHandler中的AnimationFrameCallback接口,doAnimationFrame(long frameTime)方法实现如下:
public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback {
public final boolean doAnimationFrame(long frameTime) {
...
// 处理动画的暂停和继续,这里的源码需要留意一下!后面第4节会再次提到
if (mPaused) {
mPauseTime = frameTime;
removeAnimationCallback();
return false;
} else if (mResumed) {
mResumed = false;
if (mPauseTime > 0) {
// Offset by the duration that the animation was paused
mStartTime += (frameTime - mPauseTime);
}
}
//此处忽略大量状态处理
...
//基于事件计算动画进度
boolean finished = animateBasedOnTime(currentTime);
//判断动画是否结束
if (finished) {
//处理动画结束
endAnimation();
}
return finished;
}
}ValueAnimator中的animateBasedOnTime(currentTime)方法正如方法名,依据当前时间回调执行动画:
boolean animateBasedOnTime(long currentTime) {
boolean done = false;
if (mRunning) {
...
//计算动画值的变化
animateValue(currentIterationFraction);
}
return done;
}紧接着执行animateValue(float fraction)方法。计算当前动画值。在这里会通知注册的AnimatorUpdateListener监听器,在这里开发者根据值的变化设置View的属性,形成动画。
void animateValue(float fraction) {
fraction = mInterpolator.getInterpolation(fraction);
mCurrentFraction = fraction;
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
mValues[i].calculateValue(fraction);
}
if (mUpdateListeners != null) {
int numListeners = mUpdateListeners.size();
for (int i = 0; i < numListeners; ++i) {
//回调动画监听器onAnimationUpdate,更新值
mUpdateListeners.get(i).onAnimationUpdate(this);
}
}
}ValueAnimator动画过程中的主要流程都深入的了解一遍,输出一下简化的流程图:
同样的,ObjectAnimator动画回调和ValueAnimator类似,最后更新值的变化操作不太一样,使用ObjectAnimator不需要手动更新View属性值。这是因为animateValue(float fraction)方法在ValueAnimator的子类ObjectAnimator中有所不同,不只是单纯的计算动画值的变化,由内部的PropertyValuesHolder执行setAnimatedValue(Object target)用反射设置View的属性(反射细节这里暂不深挖),从而形成动画。
@CallSuper
@Override
void animateValue(float fraction) {
final Object target = getTarget();
if (mTarget != null && target == null) {
// We lost the target reference, cancel and clean up. Note: we allow null target if the
/// target has never been set.
cancel();
return;
}
super.animateValue(fraction);
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
mValues[i].setAnimatedValue(target);
}
}ObjectAnimator动画总体流程和ValueAnimator类似:
反射的细节,这里不再赘述,由于ObjectAnimator多了一个反射过程,从动画的性能考量,使用ValueAnimator要比ObjectAnimator好一些。ObjectAnimator对动画属性操作封装的较好,开发用起来更方便。
3、动画的终止
前面了解了动画的启动start(),接下来看看动画的终止,有两个方法可以终止动画:cancel()和end()。两个方法最后都会调用endAnimation()方法终止动画:
private void endAnimation() {
//如果已经在结束中,直接返回
if (mAnimationEndRequested) {
return;
}
//从AnimationHandler中移除当前Animator回调对象
removeAnimationCallback();
//一堆状态的重置
...
mRunning = false;
mStarted = false;
mStartListenersCalled = false;
mLastFrameTime = -1;
mFirstFrameTime = -1;
mStartTime = -1;
if (notify && mListeners != null) {
ArrayList<AnimatorListener> tmpListeners =
(ArrayList<AnimatorListener>) mListeners.clone();
int numListeners = tmpListeners.size();
for (int i = 0; i < numListeners; ++i) {
//回调所有注册的AnimatorListener的onAnimationEnd方法
tmpListeners.get(i).onAnimationEnd(this, mReversing);
}
}
...
}3.1、cancel()动画
cancel()方法流程比较简单,源码如下:
@Override
public void cancel() {
if (Looper.myLooper() == null) {
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
}
if (mAnimationEndRequested) {
return;
}
if ((mStarted || mRunning) && mListeners != null) {
if (!mRunning) {
// 如果尚未运行,监听器的onAnimationStart不会调用,先通知它们。
notifyStartListeners();
}
ArrayList<AnimatorListener> tmpListeners =
(ArrayList<AnimatorListener>) mListeners.clone();
for (AnimatorListener listener : tmpListeners) {
//通知动画监听器onAnimationCancel
listener.onAnimationCancel(this);
}
}
//执行取消动画
endAnimation();
}cancel()取消动画的时序图:

3.2、end()动画
end()方法比起cancel()方法没有那么多状态位的复位,如果动画尚未启动,先启动动画;并且直接将动画执行到终点最后一帧,再结束动画。
@Override
public void end() {
if (Looper.myLooper() == null) {
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
}
if (!mRunning) {
// 如果动画还没有开始的特殊情况; 准备好结束
startAnimation();
mStarted = true;
} else if (!mInitialized) {
initAnimation();
}
//将动画结束在最后一帧,反转动画则是起始位置
animateValue(shouldPlayBackward(mRepeatCount, mReversing) ? 0f : 1f);
//结束动画
endAnimation();
}end()结束动画的时序图:

简单的理解就是动画运行过程中调用cancel()方法直接在当前画面终止动画,而end()方法终止动画会让动画停留在最后一帧并结束动画。
4、动画的暂停和继续
改变动画执行状态的方法已经看了三个:start()、cancel()、end(),还有两个:pause()、resume(),分别用来暂停动画和继续动画。当Activity界面生命周期发生变化的时候,相应的应该处理动画的播放状态。举个例子:界面再后台的时候,动画应该暂停;界面切换到前台,动画再继续播放。
4.1、暂停动画pause()
pause()暂停动画的方法中,仅涉及一些状态的切换。并没有在该方法中将当前ValueAnimator动画从AnimationHandler中移除。
@Override
public void pause() {
boolean previouslyPaused = mPaused;
//回调AnimatorPauseListener监听器 onAnimationPause
super.pause();
if (!previouslyPaused && mPaused) {
mPauseTime = -1;
mResumed = false;
}
}让动画暂停的生效的其实是在动画执行的doAnimationFrame(long frameTime)方法中,如果判断了动画mPaused暂停状态,那么就将当前AnimationFrameCallback回调从AnimationHandler中移除。
public final boolean doAnimationFrame(long frameTime) {
...
// Handle pause/resume
if (mPaused) {
mPauseTime = frameTime;
removeAnimationCallback();
return false;
} else if (mResumed) {
mResumed = false;
if (mPauseTime > 0) {
// Offset by the duration that the animation was paused
mStartTime += (frameTime - mPauseTime);
}
}
...
}4.2、继续动画resume()
再来看看resume()继续播放动画的方法,该方法和start()方法中的一样,调用addAnimationCallback(long delay)向AnimationHandler中注册AnimationFrameCallback回调开启监听。
@Override
public void resume() {
if (Looper.myLooper() == null) {
throw new AndroidRuntimeException("Animators may only be resumed from the same " +
"thread that the animator was started on");
}
if (mPaused && !mResumed) {
mResumed = true;
if (mPauseTime > 0) {
addAnimationCallback(0);
}
}
super.resume();
}在Animator父类resume()方法中设置通用状态,及回调AnimatorPauseListener监听器的onAnimationResume(Animator animation)方法:
public void resume() {
if (mPaused) {
mPaused = false;
if (mPauseListeners != null) {
ArrayList<AnimatorPauseListener> tmpListeners =
(ArrayList<AnimatorPauseListener>) mPauseListeners.clone();
int numListeners = tmpListeners.size();
for (int i = 0; i < numListeners; ++i) {
tmpListeners.get(i).onAnimationResume(this);
}
}
}
}






