当前位置: 首页 > news >正文

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 和其他应用程序之间切换时所看到的窗口过渡动画。这包括:

  1. 应用启动动画: 当用户从 Launcher (如点击图标、小部件或从概览启动任务) 启动一个应用程序时,QuickstepTransitionManager 负责创建和运行动画,使得 Launcher 界面元素(如图标、背景、工作区)能够平滑地过渡到应用程序窗口的出现。

  2. 应用关闭动画 (返回桌面): 当用户从一个应用程序通过手势或按键返回到 Launcher (桌面) 时,它负责创建和运行动画,使得应用程序窗口能够平滑地过渡(通常是缩小)到 Launcher 上的对应目标(图标、小部件或屏幕中心),同时 Launcher 界面元素(工作区、背景等)恢复显示。

  3. 概览启动动画: 管理从概览 (RecentsView) 启动任务时的特殊过渡动画。

  4. 特殊场景处理: 处理一些特殊情况下的动画,如从锁屏解锁进入 Launcher、从小部件启动应用、从预测行启动应用等。

  5. 动画参数计算: 计算动画所需的各种参数,如窗口的起始/结束位置、缩放比例、透明度、圆角、裁剪区域等。

  6. 系统动画注册: 向 Android 系统的窗口管理器 (WindowManager) 注册这些自定义的过渡动画。这通过 RemoteAnimationAdapter (旧版) 或 RemoteTransition (新版 Shell Transitions) 实现,使得系统在进行窗口切换时,能够调用 Launcher 提供的动画逻辑来取代默认的窗口动画。

简单来说,QuickstepTransitionManager 就是 Launcher3 中负责**“让应用打开和关闭看起来很酷很流畅”**的幕后导演。

工作原理 (How it Works):

其工作原理主要基于 Android 提供的远程动画 (Remote Animations / Transitions) 机制:

  1. 注册:
    • 在 Launcher 启动时 (或特定时机),QuickstepTransitionManager 会通过 SystemUiProxy 向系统注册自定义的动画。
    • 它会指定哪些窗口切换场景(由 WindowManager.TransitionTypeTransitionFilter 定义,例如 TRANSIT_OLD_WALLPAPER_OPEN, TRANSIT_OPEN/CLOSE 组合等)应该使用 Launcher 提供的动画逻辑。
    • 注册的核心是一个实现了 RemoteAnimationRunnerCompatIRemoteTransition 接口的对象 (通常是 LauncherAnimationRunner 的实例)。
// 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
  1. 触发: 当系统检测到符合注册条件的窗口切换发生时(例如,用户点击图标启动应用,系统准备关闭 Launcher 并打开目标应用),系统不会执行默认的窗口动画,而是会回调 Launcher 中注册的 RemoteAnimationRunnerCompatIRemoteTransitiononAnimationStartstartAnimation 方法。
    // 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);}}
  1. 回调参数: 系统在回调时会提供关键信息:
    • RemoteAnimationTarget[]: 一个包含所有参与过渡的窗口(Leash)信息的数组。每个 RemoteAnimationTarget 包含窗口的 SurfaceControl (Leash)、初始位置/状态、模式 (MODE_OPENINGMODE_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);}
  1. 动画执行:

    • QuickstepTransitionManageronAnimationStartstartAnimation 方法被触发后,会分析传入的 RemoteAnimationTarget[] 来理解当前的过渡场景(哪个应用在打开?哪个在关闭?Launcher 是否参与?)。
    • 根据场景(启动应用、返回桌面、从概览启动等)和触发源(图标、小部件、返回手势等),它会选择并组合相应的动画逻辑。
    • 核心动画构建:
      • 窗口动画: 主要通过 RectFSpringAnim (基于物理的弹簧动画) 或 ValueAnimator 来计算窗口 Leash 的变换(位置、缩放、裁剪、圆角、透明度)。这些计算通常涉及到目标视图(如图标)的位置、屏幕尺寸、设备配置等。TaskViewSimulator 虽然主要用于手势导航,但其原理(模拟变换)有时也会被借鉴或用于计算特定场景的窗口目标状态。
      • Launcher 内容动画: 同时,它会创建 AnimatorSet 来控制 Launcher 内部 UI 元素的动画(如 Workspace、Hotseat、背景等的淡出、缩放)。这通常通过 getLauncherContentAnimatorStaggeredWorkspaceAnim, WorkspaceRevealAnim 等辅助类实现。
      • 浮动视图动画 (FloatingIconView, FloatingWidgetView): 为了实现图标/小部件“变形”到应用窗口的效果,它会创建一个临时的浮动视图,这个视图的外观在动画过程中会从图标/小部件逐渐过渡到目标窗口的快照或背景色,并跟随窗口动画进行位移和缩放。
    • 动画同步: 将窗口动画和 Launcher 内容动画组合进一个总的 AnimatorSet 中。
    • Surface 应用: 在动画的每一帧 (ValueAnimator.AnimatorUpdateListenerRectFSpringAnim.OnUpdateListener),计算出的窗口变换参数会通过 SurfaceControl.Transaction 应用到对应的 RemoteAnimationTarget 的 Leash 上。
    • 完成回调: 在总动画集的 onAnimationEnd 监听器中,调用系统提供的 FinishedCallback,通知系统动画结束。
  2. 特殊动画处理:

    • 返回桌面 (App Close): createWallpaperOpenRunner / WallpaperOpenLauncherAnimationRunner 是处理返回桌面动画的核心。它会找到应用对应的 Launcher 视图(图标或小部件),然后创建动画将应用窗口缩小并过渡到该视图的位置和外观。
    • 应用启动 (App Launch): getActivityLaunchOptions 创建 ActivityOptions 并附加一个 AppLaunchAnimationRunnerAppLaunchAnimationRunneronAnimationStart 中根据启动源(图标、小部件、概览)选择不同的组合函数 (composeIconLaunchAnimator, composeWidgetLaunchAnimator, composeRecentsLaunchAnimator) 来构建启动动画。
    • 解锁动画 (mKeyguardGoingAwayRunner): 处理从锁屏解锁直接进入 Launcher 时的特殊动画。
    • 返回手势动画 (LauncherBackAnimationController): 处理预测性返回手势(Android 14+)中,应用窗口预览和返回到 Home 的动画。

在 Launcher3 中的作用:

QuickstepTransitionManager 是实现 Quickstep 核心视觉体验的关键部分。没有它,应用启动和关闭将使用 Android 系统默认的、较为生硬的过渡动画。它的作用体现在:

  • 提升视觉流畅度: 提供了高度定制化、与 Launcher UI 紧密结合的过渡动画,使得应用切换感觉更加自然和连贯。
  • 实现标志性动画: 负责实现 Quickstep 的标志性动画,如应用图标“展开”成应用窗口、应用窗口“缩小”回图标/小部件。
  • 连接系统与 Launcher: 作为 Launcher 和系统窗口管理器之间的桥梁,处理远程动画回调,将系统层面的窗口切换事件转化为 Launcher 内部的 UI 动画。
  • 复杂场景协调: 管理涉及多个窗口(应用、壁纸、非应用窗口如 PIP、导航栏)和 Launcher UI 元素的复杂动画同步。
  • 性能优化: 通过控制动画时序、使用 Hardware Layer、暂停不必要的视图更新等方式,优化过渡动画的性能。

总结:

QuickstepTransitionManager 是一个复杂但核心的动画管理器。它利用 Android 的远程动画机制,拦截系统默认的窗口切换,并替换为高度定制、与 Launcher UI 深度集成的平滑过渡动画。它通过精确计算窗口变换、同步 Launcher 内容动画、并处理各种特殊场景,极大地提升了 Quickstep 导航的用户体验和视觉效果。理解它的工作原理对于定制 Launcher3 的应用启动/关闭动画至关重要。

相关文章:

  • OneNet云平台
  • 创建laravel 12项目
  • [GXYCTF2019]Ping Ping Ping
  • 驯龙日记:用Pandas驾驭数据的野性
  • 在AWS Glue中实现缓慢变化维度(SCD)的三种类型
  • 深圳市富力达:SAP一体化管理助力精密制造升级 | 工博科技SAP客户案例
  • 织梦dedecms网站如何修改上一篇下一篇的标题字数
  • 【Flutter】Flutter + Unity 插件结构与通信接口封装
  • 光场的相位与偏振
  • 详解 Unreal Engine(虚幻引擎)
  • 开源网络入侵检测与防御系统:Snort
  • Spark SQL开发实战:从IDEA环境搭建到UDF/UDAF自定义函数实现
  • Maven下载aspose依赖失败的解决方法
  • BeeWorks Meet更适合企业内部使用的原因
  • Linux中线程池的简单实现 -- 线程安全的日志模块,策略模式,线程池的封装设计,单例模式,饿汉式单例模式,懒汉式单例模式
  • streamlit实现非原生的按钮触发效果 + flask实现带信息的按钮触发
  • 前端浏览器窗口交互完全指南:从基础操作到高级控制
  • 论文导读 - 基于大规模测量与多任务深度学习的电子鼻系统实现目标识别、浓度预测与状态判断
  • [计算机科学#3]:布尔逻辑 (计算机数学基础)
  • 【中级软件设计师】编译和解释程序的翻译阶段、符号表 (附软考真题)
  • 王毅会见俄罗斯外长拉夫罗夫
  • 伊朗港口爆炸已致40人死亡
  • 新任海南琼海市委副书记陈明已主持市政府党组全面工作
  • 影子调查丨起底“三无”拖拉机产销链:出口掩内销,监管如虚设
  • 我国对国家发展规划专门立法
  • 可实时追踪血液中单个细胞的穿戴医疗设备问世