窗口动画:LocalAnimationAdapter RemoteAnimationAdapter
本地动画 LocalAnimationAdapter:基本的activity切换动画
远程动画 RemoteAnimationAdapter:桌面点击启动app,app退出到桌面
LocalAnimationAdapter窗口动画时序图
note right of RootWindowContainer:mAppTransitionState的四种状态:
1. APP_STATE_IDLE = 0 初始值,prepareAppTransition设置transit时会设置state;
2. APP_STATE_READY = 1 executeAppTransition时设置成ready状态;
3. APP_STATE_RUNNING = 2;
4. APP_STATE_TIMEOUT 在prepareAppTransition时,发送一个5s的runnable,如果5s动画还没有执行设置动画超时
note right of AppTransitionController:*
1. transitionGoodToGo 判断是否可以进行动画;
2. adjustWallpaperWindowsForAppTransitionIfNeeded 调整WallpaperTarget;
3. getTransitCompatType 根据appTransition中的mNextAppTransitionRequests值、translucent、closing(opening)AppHasWallpaper计算出transit;
4. overrideWithRemoteAnimationIfSet 是否执行的是remoteAnimation,创建RemoteAnimationController;
5. applyAnimations(openingAppsForAnimation, closingAppsForAnimation, transit, animLp, voiceInteraction); 分别对openingApps和closingApps获取getAnimationTargets--->applyAnimations遍历所有的openingWcs/closingWcs执行wc.applyAnimation;
6. handleChangingApps 对changingApps执行wc.applyAnimation;
7. appTransition.goodToGo(transit, topOpeningApp)执行远程动画--->RemoteAnimationController.goodToGo;
8. handleNonAppWindowsInTransition 处理非窗口动画,比如keyguard_going_away;
9. mDisplayContent.computeImeTarget(true ); 更新输入法窗口
<5> wc.applyAnimation-->applyAnimationUnchecked 获取当前windowcontainer的动画适配器getAnimationAdapter
protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
@TransitionOldType int transit, boolean isVoiceInteraction,
@Nullable ArrayList<WindowContainer> sources) {
final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
transit, enter, isVoiceInteraction);
根据transit和enter找到动画xml资源activity_open_enter.xml,通过loadAnimation把xml资源转成Animation对象,创建一个WindowAnimationSpec对象,并把Animation对象作为构造方法的第一个参数传给了WindowAnimationSpec
Pair<AnimationAdapter, AnimationAdapter> getAnimationAdapter(WindowManager.LayoutParams lp,
@TransitionOldType int transit, boolean enter, boolean isVoiceInteraction) {
final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
WindowAnimationSpec spec = new WindowAnimationSpec(
a, mTmpPoint, mTmpRect,
getDisplayContent().mAppTransition.canSkipFirstFrame(),
appRootTaskClipMode,
true /* isAppAnimation */,
windowCornerRadius);
AnimationAdapter adapter = new LocalAnimationAdapter(spec,
getSurfaceAnimationRunner());
mSurfaceAnimator.startAnimation()执行动画,进行动画的surfacecontrol创建一个parent的surfacecontrol类型的mLeash对象,通过操控mLeash对象来实现窗口的大小、位置、透明度等动画属性的改变。最终是在SurfaceAnimationRunner.startAnimationLocked实现动画
通过mChoreographer切换到SurfaceAnimationThread线程来执行,然后创建了ValueAnimator属性动画对象,交由ValueAnimator属性动画对象的addUpdateListener方法来实现逐帧控制动画mLeash对象(surfacecontrol类型)的变化,具体的update方法的实现是在WindowAnimatonSpec类的apply方法里面。
private void startAnimationLocked(RunningAnimation a) {
final ValueAnimator anim = mAnimatorFactory.makeAnimator();
// Animation length is already expected to be scaled.
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);
}
}
// Transaction will be applied in the commit phase.
scheduleApplyTransaction();
});
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
synchronized (mCancelLock) {
if (!a.mCancelled) {
// TODO: change this back to use show instead of alpha when b/138459974 is
// fixed.
mFrameTransaction.setAlpha(a.mLeash, 1);
}
}
}
@Override
public void onAnimationEnd(Animator animation) {
synchronized (mLock) {
mRunningAnimations.remove(a.mLeash);
synchronized (mCancelLock) {
if (!a.mCancelled) {
// Post on other thread that we can push final state without jank.
mAnimationThreadHandler.post(a.mFinishCallback);
}
}
}
}
});
a.mAnim = anim;
mRunningAnimations.put(a.mLeash, a);
anim.start();
if (a.mAnimSpec.canSkipFirstFrame()) {
// If we can skip the first frame, we start one frame later.
anim.setCurrentPlayTime(mChoreographer.getFrameIntervalNanos() / NANOS_PER_MS);
}
// Immediately start the animation by manually applying an animation frame. Otherwise, the
// start time would only be set in the next frame, leading to a delay.
anim.doAnimationFrame(mChoreographer.getFrameTime());
}
前面介绍到appTransition.goodToGo(transit, topOpeningApp)执行远程动画--->RemoteAnimationController.goodToGo
App侧会继承IRemoteAnimationRunner.Stub实现 onAnimationStart方法通过ValueAnimator实现具体的动画
`public` `class` `MainActivity ``extends` `Activity {`
` ``private` `Button mButton;`
` ``private` `Handler mHandler;`
` ``private` `RemoteAnimationAdapter mRemoteAnimationAdapter;`
` ``@Override`
` ``protected` `void` `onCreate(``@Nullable` `Bundle savedInstanceState) {`
` ``super``.onCreate(savedInstanceState);`
` ``setContentView(R.layout.activity_main);`
` ``mButton = findViewById(R.id.anim);`
` ``mButton.setOnClickListener(``new` `View.OnClickListener() {`
` ``@Override`
` ``public` `void` `onClick(View view) {`
` ``ActivityOptions options = ActivityOptions.makeRemoteAnimation(mRemoteAnimationAdapter);`
` ``Intent intent = ``new` `Intent(MainActivity.``this``, SecondActivity.``class``);`
` ``startActivity(intent, options.toBundle());`
` ``}`
` ``});`
` ``mRemoteAnimationAdapter = getAnimationAdapter();`
` ``//这个是为了返回动画也交给remoteanimation`
` ``registerRemoteAnimations();`
` ``mHandler = ``new` `Handler(getMainLooper());`
` ``}`
` ``private` `void` `registerRemoteAnimations() {`
` ``RemoteAnimationDefinition definition = ``new` `RemoteAnimationDefinition();`
` ``//Demo从第二个页面返回第一个页面是TRANSIT_OLD_ACTIVITY_CLOSE类型的动画,所以这里第一个参数是TRANSIT_OLD_ACTIVITY_CLOSE;如果返回桌面应该是TRANSIT_OLD_WALLPAPER_CLOSE`
` ``definition.addRemoteAnimation(WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE,`
` ``ACTIVITY_TYPE_STANDARD, mRemoteAnimationAdapter);`
` ``registerRemoteAnimations(definition);`
` ``}`
` ``private` `RemoteAnimationAdapter getAnimationAdapter() {`
` ``AnimationRunner animationRunner = ``new` `AnimationRunner();`
` ``return` `new` `RemoteAnimationAdapter(animationRunner, ``400``/*duration 动画时长*/``, ``200``/*statusBarTransitionDelay*/``);`
` ``}`
` ``class` `AnimationRunner ``extends` `IRemoteAnimationRunner.Stub {`
` ``private` `final` `SyncRtSurfaceTransactionApplier mSyncRtTransactionApplier;`
` ``public` `AnimationRunner() {`
` ``mSyncRtTransactionApplier = ``new` `SyncRtSurfaceTransactionApplier(mButton);`
` ``}`
` ``@Override`
` ``public` `void` `onAnimationStart(``int` `transit, RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) ``throws` `RemoteException {`
` ``Slog.e(``"suiyue-test"``, ``"apps = "` `+ apps + ``" wallpapers = "` `+ wallpapers);`
` ``mHandler.post(``new` `Runnable() {`
` ``@Override`
` ``public` `void` `run() {`
` ``for` `(RemoteAnimationTarget target : apps) {`
` ``//target.leash就是需要做动画的animation-leash`
` ``//apps一般是2个 一个mode是OPENING,一个mode是CLOSING,但不排除异常情况,所以要有容错处理`
` ``//拿到了leash跟mode就可以尽情做你想要的动画,这里只是简单的做了个打开应用的alpha动画`
` ``Slog.e(``"suiyue-test"``, ``"leash = "` `+ target.leash + ``" mode = "` `+ target.mode);`
` ``if` `(target.mode == RemoteAnimationTarget.MODE_OPENING) {`
` ``ValueAnimator anim = ValueAnimator.ofFloat(``0``, ``1``);`
` ``anim.setDuration(``400``);`
` ``anim.setInterpolator(``new` `LinearInterpolator());`
` ``anim.addUpdateListener(``new` `ValueAnimator.AnimatorUpdateListener() {`
` ``@Override`
` ``public` `void` `onAnimationUpdate(ValueAnimator animation) {`
` ``SurfaceParams params = ``new` `SurfaceParams.Builder(target.leash)`
` ``.withAlpha((``float``) animation.getAnimatedValue())`
` ``.withVisibility(``true``)`
` ``.build();`
` ``mSyncRtTransactionApplier.scheduleApply(params);`
` ``}`
` ``});`
` ``anim.addListener(``new` `Animator.AnimatorListener() {`
` ``@Override`
` ``public` `void` `onAnimationStart(Animator animation) {`
` ``}`
` ``@Override`
` ``public` `void` `onAnimationEnd(Animator animation) {`
` ``//这个是动画结束给系统的回调,一定要调用,不然就系统就要等动画10s超时`
` ``invokeCallback(finishedCallback);`
` ``}`
` ``@Override`
` ``public` `void` `onAnimationCancel(Animator animation) {`
` ``}`
` ``@Override`
` ``public` `void` `onAnimationRepeat(Animator animation) {`
` ``}`
` ``});`
` ``anim.start();`
` ``}`
` ``}`
` ``}`
` ``});`
` ``}`
` ``@Override`
` ``public` `void` `onAnimationCancelled() ``throws` `RemoteException {`
` ``}`
` ``private` `void` `invokeCallback(IRemoteAnimationFinishedCallback callback) {`
` ``try` `{`
` ``callback.onAnimationFinished();`
` ``} ``catch` `(RemoteException e) {`
` ``e.printStackTrace();`
` ``}`
` ``}`
` ``}`
`}`