本文依据Android 12进行学习研讨,参考《深入了解Android内核源码》思路学习总结,如有了解不对,望各位朋友指正,别的或许留存一些疑问,留后续再探究。输出只是为了分享和提升自己。
动画初始化
依照窗口管理战略类中的界说,动画应该被分为四种类型。
-
TRANSIT_ENTER
:窗口进入。 -
TRANSIT_EXIT
:窗口移除。 -
TRANSIT_SHOW
:窗口可见。 -
TRANSIT_HIDE
:窗口隐藏。
而TRANSIT_PREVIEW_DONE
其实不算是动画,而是一个标志发动窗口完结的标志位。在WMS
的relayoutWindow
函数,会依据窗口状况判别是否要履行动画。下面代码则是判别动画的起始点。
//仅有在窗口在可见状况下且是一个发动窗口类型或者相关的appToken不隐藏时才会进行从头布局
final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
(win.mActivityRecord == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
|| win.mActivityRecord.isClientVisible());
//当时不需求从头布局、也已经有Surface,且不是在履行退出动画,则需求考虑是否履行动画
if (!shouldRelayout && winAnimator.hasSurface() && !win.mAnimatingExit) {
result |= RELAYOUT_RES_SURFACE_CHANGED;
if (!win.mWillReplaceWindow) {
......
//测验开端或者退出动画
focusMayChange = tryStartExitingAnimation(win, winAnimator, focusMayChange);
}
}
在tryStartExitingAnimation
调用了WindowStateAnimator
类型目标winAnimator
的applyAnimationLocked
函数履行动画。
private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator,boolean focusMayChange) {
int transit = WindowManagerPolicy.TRANSIT_EXIT;
//特点类型是使用窗口
if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
//发动窗口完结
transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
}
//窗口处于动画改换
if (win.inTransition()) {
focusMayChange = true;
win.mAnimatingExit = true;
} else if (win.isWinVisibleLw() && win.mDisplayContent.okToAnimate()) {
String reason = null;
//履行动画,假如未履行动画或动画失利,则开释相关资源
if (winAnimator.applyAnimationLocked(transit, false)) {
reason = "applyAnimation";
focusMayChange = true;
win.mAnimatingExit = true;
} else if (
win.isSelfAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION)
|| win.isAnimating(PARENTS | TRANSITION,ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS)|| (win.inTransition()
reason = "animating";
win.mAnimatingExit = true;
} else if (win.mDisplayContent.mWallpaperController.isWallpaperTarget(win)
&& win.mAttrs.type != TYPE_NOTIFICATION_SHADE) {
reason = "isWallpaperTarget";
win.mAnimatingExit = true;
}
.....
}
}
//资源开释
if (!win.mAnimatingExit) {
boolean stopped = win.mActivityRecord == null || win.mActivityRecord.mAppStopped;
win.mDestroying = true;
win.destroySurface(false, stopped);
}
if (mAccessibilityController.hasCallbacks()) {
mAccessibilityController.onWindowTransition(win, transit);
}
return focusMayChange;
}
applyAnimationLocked
函数选择适宜的动画类型,并设置给WindowState
,这儿也是 判别是否有设置动画的当地。假如设置了动画,调用WindowState
的startAnimation
函数。
boolean applyAnimationLocked(int transit, boolean isEntrance) {
//防止加载相同动画两次
if (mWin.isAnimating() && mAnimationIsEntrance == isEntrance) {
return true;
}
if (mWin.mAttrs.type == TYPE_INPUT_METHOD) {
mWin.getDisplayContent().adjustForImeIfNeeded();
if (isEntrance) {
mWin.setDisplayLayoutNeeded();
mService.mWindowPlacerLocked.requestTraversal();
}
}
if (mWin.mControllableInsetProvider != null) {
// All our animations should be driven by the insets control target.
return false;
}
// 假如显现处于 frozen状况,则不履行动画
if (mWin.mToken.okToAnimate()) {
int anim = mWin.getDisplayContent().getDisplayPolicy().selectAnimation(mWin, transit);
int attr = -1;
Animation a = null;
//anim不等于ANIMATION_STYLEABLE,表明给窗口指定了动画
if (anim != DisplayPolicy.ANIMATION_STYLEABLE) {//anim不等于0,表明指定了动画
if (anim != DisplayPolicy.ANIMATION_NONE) {
//加载动画资源
a = AnimationUtils.loadAnimation(mContext, anim);
}
} else {
//依据动画类型,选择默认的资源文件
switch (transit) {
case WindowManagerPolicy.TRANSIT_ENTER:
attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
break;
case WindowManagerPolicy.TRANSIT_EXIT:
attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
break;
case WindowManagerPolicy.TRANSIT_SHOW:
attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
break;
case WindowManagerPolicy.TRANSIT_HIDE:
attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
break;
}
//加载动画资源
if (attr >= 0) {
a = mWin.getDisplayContent().mAppTransition.loadAnimationAttr(
mWin.mAttrs, attr, TRANSIT_OLD_NONE);
}
}
if (a != null) {
mWin.startAnimation(a);//获取到动画资源,开端履行动画Animation目标
mAnimationIsEntrance = isEntrance;
}
} else {
mWin.cancelAnimation();
}
return mWin.isAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION);
}
WindowState
在WMS表明一个窗口目标,startAnimation
函数对动画anim进行进行初始化,封装成AnimationAdpater
类型的adapter
目标,并调用父类WindowContainer
的startAnimation
函数。WindowContainer
界说了窗口和窗口层级之间一些通用接口。WindowContainer
用来描绘动画和联络相相关的组件,以及履行动画的。
注意到这儿adpter
实践类型是LocalAnimationAdapter
,表明该动画不需求持有WindowManager
锁。重点是其构造函数的入参WindowAnimationSpec
和SurfaceAnimationRunner
目标,是后续监听VSYNC进行特点核算的当地。
void startAnimation(Animation anim) {
if (mControllableInsetProvider != null) {
return;
}
final DisplayInfo displayInfo = getDisplayInfo();
//初始化宽高
anim.initialize(mWindowFrames.mFrame.width(), mWindowFrames.mFrame.height(),
displayInfo.appWidth, displayInfo.appHeight);
anim.restrictDuration(MAX_ANIMATION_DURATION);
anim.scaleCurrentDuration(mWmService.getWindowAnimationScaleLocked());
//SurfaceAnimationRunner类型的 mWmService.mSurfaceAnimationRunner
final AnimationAdapter adapter = new LocalAnimationAdapter(
new WindowAnimationSpec(anim, mSurfacePosition, false,
0),
mWmService.mSurfaceAnimationRunner);
//getPendingTransaction剖析
startAnimation(getPengetPendingTransaction剖析dingTransaction(), adapter);
commitPendingTransaction();
}
WindowContainer.startAnimation
函数又调用了SurfaceAnimator.startAnimation
。SurfaceAnimator
首要是将一组子Surface
经过束缚重置为新的Surface
,称为Leach
,然后交由AnimationAdapter
履行动画。
// mWinAnimator.mLastHidden, ANIMATION_TYPE_WINDOW_ANIMATION
//animationFinishedCallback、animationCancelledCallback、snapshotAnim此刻为null
void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
@AnimationType int type,
@Nullable OnAnimationFinishedCallback animationFinishedCallback,
@Nullable Runnable animationCancelledCallback,
@Nullable AnimationAdapter snapshotAnim) {
mSurfaceAnimator.startAnimation(t, anim, hidden, type, animationFinishedCallback,
animationCancelledCallback, snapshotAnim, mSurfaceFreezer);
}
startAnimation
建立动画链成功之后,就会调用入参anim
履行动画。hidden
表明WindowContainer
当时持有Surface
是否可见。按前面剖析,此刻startAnimation
只要前面四个参数有值。三种动画:Surface、adapter、snapshot。
void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
@AnimationType int type,
@Nullable OnAnimationFinishedCallback animationFinishedCallback,
@Nullable Runnable animationCancelledCallback,
@Nullable AnimationAdapter snapshotAnim, @Nullable SurfaceFreezer freezer) {
//强制撤销与t相同类型的动画,并从头履行
cancelAnimation(t, true /* restarting */, true /* forwardCancel */);
mAnimation = anim;
mAnimationType = type;
mSurfaceAnimationFinishedCallback = animationFinishedCallback;
mAnimationCancelledCallback = animationCancelledCallback;
final SurfaceControl surface = mAnimatable.getSurfaceControl();
if (surface == null) {
cancelAnimation();
return;
}
//freezer==null
mLeash = freezer != null ? freezer.takeLeashForAnimation() : null;
if (mLeash == null) {
//创立动画链(SurfaceController),一起也会设置给t
mLeash = createAnimationLeash(mAnimatable, surface, t, type,
mAnimatable.getSurfaceWidth(), mAnimatable.getSurfaceHeight(), 0 /* x */,
0 /* y */, hidden, mService.mTransactionFactory);
mAnimatable.onAnimationLeashCreated(t, mLeash);
}
//开端动画链
mAnimatable.onLeashAnimationStarting(t, mLeash);
if (mAnimationStartDelayed) {
return;
}
//此刻履行AnimationAdapter目标mAnimation动画,mInnerAnimationFinishedCallback是WC的监听
mAnimation.startAnimation(mLeash, t, type, mInnerAnimationFinishedCallback);
//开端snapshot动画,此刻snapshotAnim==null
if (snapshotAnim != null) {
mSnapshot = freezer.takeSnapshotForAnimation();
if (mSnapshot == null) {
return;
}
mSnapshot.startAnimation(t, snapshotAnim, type);
}
}
按前面的剖析,这儿mAnimation
的实践类型是LocalAnimationAdapter
。其startAnimation
又调用了SurfaceAnimationRunner
目标的startAnimation
函数。
先是将动画相关内容封装成RunningAnimation
目标,并存放到mPendingAnimations
中。
然后向编舞者Choreographer
注册了VSYNC
监听,这样当信号来暂时,会调用startAnimations
函数。
void startAnimation(AnimationSpec a, SurfaceControl animationLeash, Transaction t,
Runnable finishCallback) {
synchronized (mLock) {
final RunningAnimation runningAnim = new RunningAnimation(a, animationLeash,
finishCallback);
//这样帧信号来暂时,会履行该Map中所有动画
mPendingAnimations.put(animationLeash, runningAnim);
//假如当时动画部推迟履行,则立即向Choreographer注册笔直信号监听
//这样笔直信号来暂时,履行startAnimations,存在必定推迟
if (!mAnimationStartDeferred) {
mChoreographer.postFrameCallback(this::startAnimations);
}
//一些动画需求初始并使用一些改换
applyTransformation(runningAnim, t, 0 /* currentPlayTime */);
}
}
SurfaceAnimationRunner
的startAnimations
函数。
private void startAnimations(long frameTimeNanos) {
synchronized (mLock) {
startPendingAnimationsLocked();
}
mPowerManagerInternal.setPowerBoost(Boost.INTERACTION, 0);
}
遍历mPendingAnimations
中所有等待帧信号降临的RunningAnimation
目标,调用startAnimationLocked
履行它们。
private void startPendingAnimationsLocked() {
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
startAnimationLocked(mPendingAnimations.valueAt(i));
}
mPendingAnimations.clear();
}
SurfaceAnimatorRunner
目标,startAnimationLocked
首要为每个RunningAnimation
动画创立ValueAnimator
目标并设置相关参数,并在AnimatorUpdateListener
回调中核算动画使用目标的相关特点。
@GuardedBy("mLock")
private void startAnimationLocked(RunningAnimation a) {
final ValueAnimator anim = mAnimatorFactory.makeAnimator();
//设置动画相关参数
anim.overrideDurationScale(1.0f);
anim.setDuration(a.mAnimSpec.getDuration());
//更改动画目标相关特点
anim.addUpdateListener(animation -> {
synchronized (mCancelLock) {
if (!a.mCancelled) {
final long duration = anim.getDuration();
long currentPlayTime = anim.getCurrentPlayTime();
if (currentPlayTime > duration) {
currentPlayTime = duration;
}
//每次更改相关动画特点
applyTransformation(a, mFrameTransaction, currentPlayTime);
}
}
scheduleApplyTransaction();
});
//anim开端后,会回调此处。
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
synchronized (mCancelLock) {
if (!a.mCancelled) {
mFrameTransaction.setAlpha(a.mLeash, 1);
}
}
}
@Override
public void onAnimationEnd(Animator animation) {
synchronized (mLock) {
mRunningAnimations.remove(a.mLeash);
synchronized (mCancelLock) {
if (!a.mCancelled) {
mAnimationThreadHandler.post(a.mFinishCallback);
}
}
}
}
});
a.mAnim = anim;
mRunningAnimations.put(a.mLeash, a);
//调用ValueAnimator的start函数。
anim.start();
if (a.mAnimSpec.canSkipFirstFrame()) {
anim.setCurrentPlayTime(mChoreographer.getFrameIntervalNanos() / NANOS_PER_MS);
}
//手动触发一帧动画特点
anim.doAnimationFrame(mChoreographer.getFrameTime());
}
ValueAnimator.start=>start(false),
该函数首要ValueAnimator
目标对一些变量进行初始化。其间调用了addAnimationCallback(0)
向AnimationHandler
注册帧信号的监听。
private void start(boolean playBackwards) {
if (Looper.myLooper() == null) {
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
}
mReversing = playBackwards;//此刻false,表明为正向动画
mSelfPulse = !mSuppressSelfPulseRequested;
//判别是否快进到某个时刻点
if (playBackwards && mSeekFraction != -1 && mSeekFraction != 0) {
if (mRepeatCount == INFINITE) {
// Calculate the fraction of the current iteration.
float fraction = (float) (mSeekFraction - Math.floor(mSeekFraction));
mSeekFraction = 1 - fraction;
} else {
mSeekFraction = 1 + mRepeatCount - mSeekFraction;
}
}
mStarted = true;
mPaused = false;
mRunning = false;
mAnimationEndRequested = false;
mLastFrameTime = -1;
mFirstFrameTime = -1;
mStartTime = -1;
addAnimationCallback(0);
if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
//内部初始化动画目标所使用的特点,和回调开端监听
startAnimation();
//初始化mStartTime
if (mSeekFraction == -1) {
setCurrentPlayTime(0);
} else {
setCurrentFraction(mSeekFraction);
}
}
}
AnimationHandler
在线程中静态单例的,在默认状况下,向编舞者Choreographer
注册并接纳其帧信号(笔直信号)回调, 向所有的动画ValueAnimator
目标发送刷新帧的时刻,这样它们在同一个线程以相同的时刻履行各自窗口特点值的核算,抵达视觉动画作用。AnimationHandler
也为咱们供给 设置类似编舞者供给周期信号的 接口,方便测验和特定功能开发。
private void addAnimationCallback(long delay) {
if (!mSelfPulse) {
return;
}
getAnimationHandler().addAnimationFrameCallback(this, delay);
}
public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
//注册笔直信号监听
if (mAnimationCallbacks.size() == 0) {
getProvider().postFrameCallback(mFrameCallback);
}
//防止重复增加
if (!mAnimationCallbacks.contains(callback)) {
mAnimationCallbacks.add(callback);
}
//延时履行
if (delay > 0) {
mDelayedCallbackStartTime.put(callback, (SystemClock.uptimeMillis() + delay));
}
}
//这样笔直信号降临,会调用doFrame函数
private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
doAnimationFrame(getProvider().getFrameTime());
if (mAnimationCallbacks.size() > 0) {
getProvider().postFrameCallback(this);
}
}
};
动画触发
AnimationHandler
默认状况会向编舞者Choreographer
注册笔直信号(VSYNC
)监听,这样当笔直信号来暂时,就回调mFrameCallback
目标doFrame
函数。
doFrame
函数获取当时帧时刻并传递给doAnimationFrame
函数,假如履行完之后,还有动画没有履行完结则再次监听VSYNC。所以在doAnimationFrame
函数中履行动画完毕后肯定将AnimationFrameCallback
目标从mAnimationCallbacks
移除。
private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
doAnimationFrame(getProvider().getFrameTime());
if (mAnimationCallbacks.size() > 0) {
getProvider().postFrameCallback(this);
}
}
};
doAnimationFrame
函数遍历mAnimationCallbacks
中所有AnimationFrameCallback
目标,判别其是否抵达开端履行动画(部分动画或许设置延时履行),抵达开端时刻,则调用它们的doAnimationFrame
函数。
private void doAnimationFrame(long frameTime) {
long currentTime = SystemClock.uptimeMillis();
final int size = mAnimationCallbacks.size();
for (int i = 0; i < size; i++) {
final AnimationFrameCallback callback = mAnimationCallbacks.get(i);
if (callback == null) {
continue;
}
//判别动画是否抵达开端履行时刻
if (isCallbackDue(callback, currentTime)) {
callback.doAnimationFrame(frameTime);//回调AnimationFrameCallback,进行逻辑处理
if (mCommitCallbacks.contains(callback)) {//检查在哪里注册到该map,推迟大的时分
getProvider().postCommitCallback(new Runnable() {
@Override
public void run() {
//延时问题
commitAnimationFrame(callback, getProvider().getFrameTime());
}
});
}
}
}
cleanUpList();
}
ValueAnimator
目标doAnimationFrame
函数。在VSYNC
来暂时,需求依据一些状况调整动画的开端时刻mStartTime
。动画未开端、康复动画、暂停动画、动画快进、动画推迟履行都会调整动画的开端时刻。假如此刻动画未开端,此帧时刻则是开端时刻,或者开端倒计时的时刻(动画设置延时履行)。假如当时是康复动画,开端时刻则更改为当时时刻节点+已暂停时刻(mStartTime+elapseTime),而不是停留在前次动画的帧时刻。这儿或许会了解为从继续前次暂停的动画作用,然后继续履行后续动画。假如此刻仍是榜首帧时刻,还需求判别是否存在动画快进的状况。
终究调用animateBasedOnTime
函数核算此刻此刻动画的相关特点值。参数为帧时刻(开端之后)或者开端时刻(刚开端)。
public final boolean doAnimationFrame(long frameTime) {
//动画刚初始化,mStartTime=-1,未开端
if (mStartTime < 0) {
// 榜首帧动画时刻,假如有推迟开端动画,此刻开端倒计时
mStartTime = mReversing
? frameTime
: frameTime + (long) (mStartDelay * resolveDurationScale());
}
if (mPaused) {//暂停
mPauseTime = frameTime;
removeAnimationCallback();
return false;
} else if (mResumed) {//康复
mResumed = false;
if (mPauseTime > 0) {
//康复并不是从前次动画进展节点康复,而是以当时帧时刻为开端
mStartTime += (frameTime - mPauseTime);
}
}
if (!mRunning) {
//动画开端时刻未到,而且没有快进
if (mStartTime > frameTime && mSeekFraction == -1) {
return false;
} else {
mRunning = true;
//初始化ValueAnimator中各个特点值
startAnimation();
}
}
if (mLastFrameTime < 0) {//此次榜首帧时刻
if (mSeekFraction >= 0) {
long seekTime = (long) (getScaledDuration() * mSeekFraction);
mStartTime = frameTime - seekTime;
mSeekFraction = -1;
}
mStartTimeCommitted = false; // allow start time to be compensated for jank
}
mLastFrameTime = frameTime;
//防止当时帧时刻比开端时刻早的问题
final long currentTime = Math.max(frameTime, mStartTime);
//核算特点值
boolean finished = animateBasedOnTime(currentTime);
if (finished) {
endAnimation();//移除FrameCallback监听,通知已注册监听
}
return finished;
}
咱们知道动画是可以指定重复次数或无限循环的。所以animateBasedOnTime
函数核算出本次帧时刻来暂时,本次动画进展在整体进展状况fraction
。0表明刚开端履行动画;0-1表明榜首次动画某个时刻点;等于1表明刚好履行完榜首次动画;大于1则表明开端循环动画。当大于1时,正数部分表明第几次重复动画,而小数部分表明本次动画的时刻节点;正数部分假如大于前次fraction,则表明是新的循环。
这个函数有许多规划妙处。
boolean animateBasedOnTime(long currentTime) {
boolean done = false;
if (mRunning) {
//获取持续时刻
final long scaledDuration = getScaledDuration();
//currentTime - mStartTime表明动画已履行完的时刻长度,等于0表明刚开端,大于0,说明要越过这部分时刻。
//(float)(currentTime - mStartTime) / scaledDuration大于1表明已经开端重复履行动画了,0-1则是榜首次。1刚好榜首次动画完毕
final float fraction = scaledDuration > 0 ?
(float)(currentTime - mStartTime) / scaledDuration : 1f;
final float lastFraction = mOverallFraction;
//fraction在整型比上一次大,则判别为新一次循环,持平判别为同一次动画内的不同阶段
final boolean newIteration = (int) fraction > (int) lastFraction;
//判别是否终究一次动画循环:在有限循环次数内,本次动画等于或超出设置的总重复次数
final boolean lastIterationFinished = (fraction >= mRepeatCount + 1) &&
(mRepeatCount != INFINITE);
if (scaledDuration == 0) {
//持续时刻为0的,直接完毕
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) {
done = true;//当时属于终究一次迭代
}
mOverallFraction = clampFraction(fraction);//缓存本次进展节点
//先核算本次动画是第几次iteration
//再取小数部分curFraction=fraction-iteration,依据是否反向动画,确定终究的进展curFraction or 1-curFraction
float currentIterationFraction = getCurrentIterationFraction(
mOverallFraction, mReversing);
animateValue(currentIterationFraction);//经过插值器核算动画特点值
}
return done;
}
animateValue
函数以本次动画时刻进展节点,经过时刻插值器改换进展节点,然后通知特点数组mValues
中的目标,让它们依据改换后fraction
,转化具体的特点值。然后回调UpdateListener
目标的onAnimationUpdate
函数。
void animateValue(float fraction) {
//插值器改换fraction
fraction = mInterpolator.getInterpolation(fraction);
mCurrentFraction = fraction;
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
//各个特点依据fraction转化自己的值
mValues[i].calculateValue(fraction);
}
if (mUpdateListeners != null) {
int numListeners = mUpdateListeners.size();
for (int i = 0; i < numListeners; ++i) {
//回调通知
mUpdateListeners.get(i).onAnimationUpdate(this);
}
}
}
这就回到了SurfaceAnimatorRunner
对像startAnimationLocked
函数给ValueAnimator
设置监听的当地。
private void startAnimationLocked(RunningAnimation a) {
......
//帧动画经过valueAnimator核算发生后回调此处
anim.addUpdateListener(animation -> {
synchronized (mCancelLock) {
if (!a.mCancelled) {
final long duration = anim.getDuration();
long currentPlayTime = anim.getCurrentPlayTime();
if (currentPlayTime > duration) {//履行完毕
currentPlayTime = duration;
}
//动画特点核算
applyTransformation(a, mFrameTransaction, currentPlayTime);
}
}
// Transaction will be applied in the commit phase.
scheduleApplyTransaction();
});
......
}
applyTransformation
函数内部有调用了WindowAnimationSpec
目标的apply
函数。
private void applyTransformation(RunningAnimation a, Transaction t, long currentPlayTime) {
a.mAnimSpec.apply(t, a.mLeash, currentPlayTime);
}
apply
函数获取线程本地TmpValues
目标,将相关特点核算结果写到其Transformation
类型的transformation
成员变量。Transformation
类封装Matrix
、裁剪、透明度、动画类型。而Matrix
可以对目标进行缩放、平移、和旋转。也就是说,Transformation
类型囊括了四个动画类型缩放、平移、旋转、透明度,代表了动画某刻要使用的改换。
public void apply(Transaction t, SurfaceControl leash, long currentPlayTime) {
final TmpValues tmp = mThreadLocalTmps.get();
//重置transformation
tmp.transformation.clear();
//核算某个时刻的动画特点,并将结果写会tmp.transformation
mAnimation.getTransformation(currentPlayTime, tmp.transformation);
//位移
tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y);
//旋转、缩放
t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats);
//透明度
t.setAlpha(leash, tmp.transformation.getAlpha());
boolean cropSet = false;
if (mRootTaskClipMode == ROOT_TASK_CLIP_NONE) {
if (tmp.transformation.hasClipRect()) {
t.setWindowCrop(leash, tmp.transformation.getClipRect());
cropSet = true;
}
} else {
mTmpRect.set(mRootTaskBounds);
if (tmp.transformation.hasClipRect()) {
mTmpRect.intersect(tmp.transformation.getClipRect());
}
t.setWindowCrop(leash, mTmpRect);
cropSet = true;
}
//设置圆角
if (cropSet && mAnimation.hasRoundedCorners() && mWindowCornerRadius > 0) {
t.setCornerRadius(leash, mWindowCornerRadius);
}
}
代码中调用了Animation
的getTransformation
函数,首要是核算动画的状况,是否开端、运转、完毕。假如动画仍是处于运转状况,则调用getTransformationAt
函数。
public boolean getTransformation(long currentTime, Transformation outTransformation) {
if (mStartTime == -1) {
mStartTime = currentTime;
}
final long startOffset = getStartOffset();
final long duration = mDuration;
float normalizedTime;
//核算此刻在本次动画的时刻节点
if (duration != 0) {
//核算当时所处的方位0
normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) /
(float) duration;
} else {
//未开端或者完毕了
normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;
}
//动画完毕了,或者被撤销。
final boolean expired = normalizedTime >= 1.0f || isCanceled();
mMore = !expired;
if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) {
if (!mStarted) {
fireAnimationStart();//回调监听
mStarted = true;
if (NoImagePreloadHolder.USE_CLOSEGUARD) {
guard.open("cancel or detach or getTransformation");
}
}
//normalized在0f~1f之间
if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
//此刻是否反向动画
if (mCycleFlip) {
normalizedTime = 1.0f - normalizedTime;
}
//将动画特点缓冲到outTransformation
getTransformationAt(normalizedTime, outTransformation);
}
//完毕了,但是或许循环动画
if (expired) {
if (mRepeatCount == mRepeated || isCanceled()) {//动画完毕
if (!mEnded) {
mEnded = true;
guard.close();
fireAnimationEnd();
}
} else {//动画循环
if (mRepeatCount > 0) {
mRepeated++;
}
if (mRepeatMode == REVERSE) {
mCycleFlip = !mCycleFlip;
}
mStartTime = -1;
mMore = true;
fireAnimationRepeat();
}
}
if (!mMore && mOneMoreTime) {
mOneMoreTime = false;
return true;
}
return mMore;
}
getTransformationAt
函数内部又调用Animation
的applyTransformation
函数。这儿的Animation
子类会重写该函数,完成自己的特定特点核算。Animation
子类可所以在主题或者指定的Animation
为准,如前面由系统默认指定的动画。
public void getTransformationAt(float normalizedTime, Transformation outTransformation) {
final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
applyTransformation(interpolatedTime, outTransformation);
}
动画的展示
回到了SurfaceAnimatorRunner
对像startAnimationLocked
函数给ValueAnimator
设置监听的当地。在上面履行了applyTransformation函数之后,调用了applyTransformation。
private final Runnable mApplyTransactionRunnable = this::applyTransaction;
private void scheduleApplyTransaction() {
if (!mApplyScheduled) {
mChoreographer.postCallback(CALLBACK_TRAVERSAL, mApplyTransactionRunnable,
null /* token */);
mApplyScheduled = true;
}
}
private void applyTransaction() {
mFrameTransaction.setAnimationTransaction();
mFrameTransaction.setFrameTimelineVsync(mChoreographer.getVsyncId());
mFrameTransaction.apply();
mApplyScheduled = false;
}
依据前面mSurfaceAnimationRunner目标来自WMS的成员变量,其在WMS创立的时分被创立,Transaction类型的mFrameTransaction目标以同步方式设置SurfaceController。applyTransaction函数调用mFrameTransaction目标的几个方法,内部都调用底层代码去设置Surface。这儿不再进一步跟进。
总结
经过本文对动画源码的学习,了解在动画上面临Float浮点数奇妙运用,用来合理操控动画的重复行为和单次进展。
一起也了解到动画在底层也是经过ValueAnimator来核算动画的各个特点 ,因而进一步确定原理,动画就是在指定的时刻内播放一帧帧图像,依据人眼对图像的感知特色,然后构成动效。
别的,动画会以笔直信号来初始化动画和触发动画的开端。