AOSP Android14 Launcher3——动画核心类QuickstepTransitionManager详解
Launcher3中,有一个类在跟桌面相关的各种动画中扮演着非常关键的角色,这个类就是QuickstepTransitionManager。
QuickstepTransitionManager在aosp中的路径为:aosp/packages/apps/Launcher3/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
接下来我们来深入分析 QuickstepTransitionManager.java
这个类。它是 Quickstep (Launcher3 的手势导航和过渡动画核心实现) 中至关重要的部分,负责管理和协调各种复杂的应用程序启动和关闭过渡动画。
核心作用 (Core Role):
QuickstepTransitionManager
的主要职责是定义、注册和执行当用户在 Launcher 和其他应用程序之间切换时所看到的窗口过渡动画。这包括:
-
应用启动动画: 当用户从 Launcher (如点击图标、小部件或从概览启动任务) 启动一个应用程序时,
QuickstepTransitionManager
负责创建和运行动画,使得 Launcher 界面元素(如图标、背景、工作区)能够平滑地过渡到应用程序窗口的出现。 -
应用关闭动画 (返回桌面): 当用户从一个应用程序通过手势或按键返回到 Launcher (桌面) 时,它负责创建和运行动画,使得应用程序窗口能够平滑地过渡(通常是缩小)到 Launcher 上的对应目标(图标、小部件或屏幕中心),同时 Launcher 界面元素(工作区、背景等)恢复显示。
-
概览启动动画: 管理从概览 (RecentsView) 启动任务时的特殊过渡动画。
-
特殊场景处理: 处理一些特殊情况下的动画,如从锁屏解锁进入 Launcher、从小部件启动应用、从预测行启动应用等。
-
动画参数计算: 计算动画所需的各种参数,如窗口的起始/结束位置、缩放比例、透明度、圆角、裁剪区域等。
-
系统动画注册: 向 Android 系统的窗口管理器 (WindowManager) 注册这些自定义的过渡动画。这通过
RemoteAnimationAdapter
(旧版) 或RemoteTransition
(新版 Shell Transitions) 实现,使得系统在进行窗口切换时,能够调用 Launcher 提供的动画逻辑来取代默认的窗口动画。
简单来说,QuickstepTransitionManager
就是 Launcher3 中负责**“让应用打开和关闭看起来很酷很流畅”**的幕后导演。
工作原理 (How it Works):
其工作原理主要基于 Android 提供的远程动画 (Remote Animations / Transitions) 机制:
- 注册:
- 在 Launcher 启动时 (或特定时机),
QuickstepTransitionManager
会通过SystemUiProxy
向系统注册自定义的动画。 - 它会指定哪些窗口切换场景(由
WindowManager.TransitionType
或TransitionFilter
定义,例如TRANSIT_OLD_WALLPAPER_OPEN
,TRANSIT_OPEN/CLOSE
组合等)应该使用 Launcher 提供的动画逻辑。 - 注册的核心是一个实现了
RemoteAnimationRunnerCompat
或IRemoteTransition
接口的对象 (通常是LauncherAnimationRunner
的实例)。
- 在 Launcher 启动时 (或特定时机),
// quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.javaprotected void setupViews() {super.setupViews();......省略mAppTransitionManager = buildAppTransitionManager();//向系统注册自定义动画mAppTransitionManager.registerRemoteAnimations();......省略}
//quickstep/src/com/android/launcher3/QuickstepTransitionManager.javapublic void registerRemoteAnimations() {if (SEPARATE_RECENTS_ACTIVITY.get()) {return;}RemoteAnimationDefinition definition = new RemoteAnimationDefinition();addRemoteAnimations(definition);mLauncher.registerRemoteAnimations(definition);}/*** Adds remote animations to a {@link RemoteAnimationDefinition}. May be overridden to add* additional animations.*///quickstep/src/com/android/launcher3/QuickstepTransitionManager.javaprivate void addRemoteAnimations(RemoteAnimationDefinition definition) {mWallpaperOpenRunner = createWallpaperOpenRunner(false /* fromUnlock */);definition.addRemoteAnimation(WindowManager.TRANSIT_OLD_WALLPAPER_OPEN,WindowConfiguration.ACTIVITY_TYPE_STANDARD,new RemoteAnimationAdapter(// 创建LauncherAnimationRunner 对象new LauncherAnimationRunner(mHandler, mWallpaperOpenRunner,false /* startAtFrontOfQueue */),CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));if (KEYGUARD_ANIMATION.get()) {mKeyguardGoingAwayRunner = createWallpaperOpenRunner(true /* fromUnlock */);definition.addRemoteAnimation(WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER,new RemoteAnimationAdapter(new LauncherAnimationRunner(mHandler, mKeyguardGoingAwayRunner,true /* startAtFrontOfQueue */),CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));}}
其中的LauncherAnimationRunner继承自RemoteAnimationRunnerCompat
RemoteAnimationRunnerCompat就是远程动画类,路径是:packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java
public class LauncherAnimationRunner extends RemoteAnimationRunnerCompat
- 触发: 当系统检测到符合注册条件的窗口切换发生时(例如,用户点击图标启动应用,系统准备关闭 Launcher 并打开目标应用),系统不会执行默认的窗口动画,而是会回调 Launcher 中注册的
RemoteAnimationRunnerCompat
或IRemoteTransition
的onAnimationStart
或startAnimation
方法。
// Called only in S+ platform//quickstep/src/com/android/launcher3/LauncherAnimationRunner.java@BinderThreadpublic void onAnimationStart(int transit,RemoteAnimationTarget[] appTargets,RemoteAnimationTarget[] wallpaperTargets,RemoteAnimationTarget[] nonAppTargets,Runnable runnable) {Runnable r = () -> {finishExistingAnimation();mAnimationResult = new AnimationResult(() -> mAnimationResult = null, runnable);getFactory().onAnimationStart(transit, appTargets, wallpaperTargets, nonAppTargets,mAnimationResult);};if (mStartAtFrontOfQueue) {postAtFrontOfQueueAsynchronously(mHandler, r);} else {postAsyncCallback(mHandler, r);}}
- 回调参数: 系统在回调时会提供关键信息:
RemoteAnimationTarget[]
: 一个包含所有参与过渡的窗口(Leash)信息的数组。每个RemoteAnimationTarget
包含窗口的 SurfaceControl (Leash)、初始位置/状态、模式 (MODE_OPENING
或MODE_CLOSING
) 等。IRemoteAnimationFinishedCallback
/IRemoteTransitionFinishedCallback
: 一个回调接口,动画完成后 Launcher 必须调用它来通知系统动画结束,以便系统可以清理资源并完成切换。
上面的onAnimationStart方法中又会去调用其他动画类的onAnimationStart回调方法
getFactory().onAnimationStart(transit, appTargets, wallpaperTargets, nonAppTargets,mAnimationResult);
这里的goFactory得到的是一个接口RemoteAnimationFactory,它的实现类有如下几个:
其中后面三个AppLauncherAnimationRunner、ContainerAnimationRunner、WallpaperOpenLauncherAnimationRunner三个类都是QuickstepTransitionManager的内部动画类
在QuickstepTransitionManager的getActivityLaunchOptions中,会创建AppLauncherAnimationRunner和ContainerAnimationRunner的对象。在option中会附加上这些动画信息,在应用启动后最终回回调这几个类的onAnimationStart方法
public ActivityOptionsWrapper getActivityLaunchOptions(View v) {boolean fromRecents = isLaunchingFromRecents(v, null /* targets */);RunnableList onEndCallback = new RunnableList();// Handle the case where an already visible task is launched which results in no transitionTaskRestartedDuringLaunchListener restartedListener =new TaskRestartedDuringLaunchListener();restartedListener.register(onEndCallback::executeAllAndDestroy);onEndCallback.add(restartedListener::unregister);mAppLaunchRunner = new AppLaunchAnimationRunner(v, onEndCallback);ItemInfo tag = (ItemInfo) v.getTag();if (tag != null && tag.shouldUseBackgroundAnimation()) {ContainerAnimationRunner containerAnimationRunner = ContainerAnimationRunner.from(v, mLauncher, mStartingWindowListener, onEndCallback);if (containerAnimationRunner != null) {mAppLaunchRunner = containerAnimationRunner;}}RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mHandler, mAppLaunchRunner, true /* startAtFrontOfQueue */);// Note that this duration is a guess as we do not know if the animation will be a// recents launch or not for sure until we know the opening app targets.long duration = fromRecents? RECENTS_LAUNCH_DURATION: APP_LAUNCH_DURATION;long statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION- STATUS_BAR_TRANSITION_PRE_DELAY;ActivityOptions options = ActivityOptions.makeRemoteAnimation(new RemoteAnimationAdapter(runner, duration, statusBarTransitionDelay),new RemoteTransition(runner.toRemoteTransition(),mLauncher.getIApplicationThread(), "QuickstepLaunch"));return new ActivityOptionsWrapper(options, onEndCallback);}
-
动画执行:
QuickstepTransitionManager
的onAnimationStart
或startAnimation
方法被触发后,会分析传入的RemoteAnimationTarget[]
来理解当前的过渡场景(哪个应用在打开?哪个在关闭?Launcher 是否参与?)。- 根据场景(启动应用、返回桌面、从概览启动等)和触发源(图标、小部件、返回手势等),它会选择并组合相应的动画逻辑。
- 核心动画构建:
- 窗口动画: 主要通过
RectFSpringAnim
(基于物理的弹簧动画) 或ValueAnimator
来计算窗口 Leash 的变换(位置、缩放、裁剪、圆角、透明度)。这些计算通常涉及到目标视图(如图标)的位置、屏幕尺寸、设备配置等。TaskViewSimulator
虽然主要用于手势导航,但其原理(模拟变换)有时也会被借鉴或用于计算特定场景的窗口目标状态。 - Launcher 内容动画: 同时,它会创建
AnimatorSet
来控制 Launcher 内部 UI 元素的动画(如 Workspace、Hotseat、背景等的淡出、缩放)。这通常通过getLauncherContentAnimator
或StaggeredWorkspaceAnim
,WorkspaceRevealAnim
等辅助类实现。 - 浮动视图动画 (
FloatingIconView
,FloatingWidgetView
): 为了实现图标/小部件“变形”到应用窗口的效果,它会创建一个临时的浮动视图,这个视图的外观在动画过程中会从图标/小部件逐渐过渡到目标窗口的快照或背景色,并跟随窗口动画进行位移和缩放。
- 窗口动画: 主要通过
- 动画同步: 将窗口动画和 Launcher 内容动画组合进一个总的
AnimatorSet
中。 - Surface 应用: 在动画的每一帧 (
ValueAnimator.AnimatorUpdateListener
或RectFSpringAnim.OnUpdateListener
),计算出的窗口变换参数会通过SurfaceControl.Transaction
应用到对应的RemoteAnimationTarget
的 Leash 上。 - 完成回调: 在总动画集的
onAnimationEnd
监听器中,调用系统提供的FinishedCallback
,通知系统动画结束。
-
特殊动画处理:
- 返回桌面 (App Close):
createWallpaperOpenRunner
/WallpaperOpenLauncherAnimationRunner
是处理返回桌面动画的核心。它会找到应用对应的 Launcher 视图(图标或小部件),然后创建动画将应用窗口缩小并过渡到该视图的位置和外观。 - 应用启动 (App Launch):
getActivityLaunchOptions
创建ActivityOptions
并附加一个AppLaunchAnimationRunner
。AppLaunchAnimationRunner
在onAnimationStart
中根据启动源(图标、小部件、概览)选择不同的组合函数 (composeIconLaunchAnimator
,composeWidgetLaunchAnimator
,composeRecentsLaunchAnimator
) 来构建启动动画。 - 解锁动画 (
mKeyguardGoingAwayRunner
): 处理从锁屏解锁直接进入 Launcher 时的特殊动画。 - 返回手势动画 (
LauncherBackAnimationController
): 处理预测性返回手势(Android 14+)中,应用窗口预览和返回到 Home 的动画。
- 返回桌面 (App Close):
在 Launcher3 中的作用:
QuickstepTransitionManager
是实现 Quickstep 核心视觉体验的关键部分。没有它,应用启动和关闭将使用 Android 系统默认的、较为生硬的过渡动画。它的作用体现在:
- 提升视觉流畅度: 提供了高度定制化、与 Launcher UI 紧密结合的过渡动画,使得应用切换感觉更加自然和连贯。
- 实现标志性动画: 负责实现 Quickstep 的标志性动画,如应用图标“展开”成应用窗口、应用窗口“缩小”回图标/小部件。
- 连接系统与 Launcher: 作为 Launcher 和系统窗口管理器之间的桥梁,处理远程动画回调,将系统层面的窗口切换事件转化为 Launcher 内部的 UI 动画。
- 复杂场景协调: 管理涉及多个窗口(应用、壁纸、非应用窗口如 PIP、导航栏)和 Launcher UI 元素的复杂动画同步。
- 性能优化: 通过控制动画时序、使用 Hardware Layer、暂停不必要的视图更新等方式,优化过渡动画的性能。
总结:
QuickstepTransitionManager
是一个复杂但核心的动画管理器。它利用 Android 的远程动画机制,拦截系统默认的窗口切换,并替换为高度定制、与 Launcher UI 深度集成的平滑过渡动画。它通过精确计算窗口变换、同步 Launcher 内容动画、并处理各种特殊场景,极大地提升了 Quickstep 导航的用户体验和视觉效果。理解它的工作原理对于定制 Launcher3 的应用启动/关闭动画至关重要。