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

AOSP Android14 Launcher3——点击桌面图标启动应用动画流程

在Launcher3中,点击桌面应用图标时,会有一个从 图标位置起始到全屏的动画过程,使得应用的打开过程不是生硬的启动过程。

这个动画具体是怎么实现的呢?本文对这个过程进行一个梳理

在Launcher中,动画大体上可以分为两类,一种是Launcher3本身的动画,对Launcher3中的UI元素进行动画;还有一类是远程窗口的动画,也就是跨进程的动画。在启动应用,从应用回到Launcher,分屏,壁纸等等场景,使用的动画就是这类远程窗口动画。这类动画都会涉及到SystemUI,其中有几个核心接口类RemoteAnimationRunnerCompat,RemoteAnimationTargetCompat,整体动画过程是一个涉及到Launcher、WM、SystemUI等多个模块的过程。下面就来介绍详细的动画流程。

详细动画流程:

  1. 点击与启动请求:

    • 用户点击桌面图标 (BubbleTextViewFolderIcon)。
    • ItemClickHandler 或 View 自身的 onClick 触发。
    • 构建 Intent 并调用 Launcher.startActivitySafely()
  2. 生成 ActivityOptions (由 QuickstepTransitionManager 主导):

    • Launcher.startActivitySafely() 调用 Launcher.getActivityLaunchOptions()
    • Launcher.getActivityLaunchOptions() 调用 QuickstepTransitionManager 实例的 getActivityLaunchOptions(View v) 方法
    • QuickstepTransitionManager.getActivityLaunchOptions:
      • 判断启动来源(这里是从桌面图标,isLaunchingFromRecents 返回 false)。
      • 创建一个 AppLaunchAnimationRunner (实现了 RemoteAnimationFactory 接口) 实例,并传入一个 RunnableList 用于动画结束后的回调。
      • 创建一个 LauncherAnimationRunner (实现了 RemoteAnimationRunnerCompat 接口),包装 AppLaunchAnimationRunner
      • 使用 ActivityOptions.makeRemoteAnimation(...) 创建 ActivityOptions,将 LauncherAnimationRunner 注册给系统,并指定动画预估时长 (APP_LAUNCH_DURATION) 和状态栏动画延迟 (statusBarTransitionDelay)。
      • 返回包含这些 ActivityOptionsActivityOptionsWrapper
    • 这个过程的核心是告诉系统:“启动这个应用,但请把动画控制权通过远程动画回调交给我 (Launcher)”。
  3. 系统准备与回调:

    • ActivityTaskManagerService 处理启动请求,准备应用进程和窗口。
    • WindowManager 在应用窗口就绪后,通过 Binder 回调在步骤 2 中注册的 LauncherAnimationRunner,最终调用到 AppLaunchAnimationRunner.onCreateAnimation 方法,并传递 RemoteAnimationTarget 数组。
  4. Launcher 执行动画 (QuickstepTransitionManager.AppLaunchAnimationRunner.onCreateAnimation):

    • 接收 Targets: onCreateAnimation 方法被调用,接收到代表各个窗口/Surface 的 RemoteAnimationTarget 数组 (包括 MODE_OPENING 的应用,MODE_CLOSING 的 Launcher,以及壁纸等)。
    • 判断启动类型: 代码确认启动源不是 Widget 或 Recents,执行图标启动逻辑。
    • 构建核心动画 (composeIconLaunchAnimator): 这是关键步骤,构建一个 AnimatorSet 来编排整个动画:
      • 链接状态机: 调用 mLauncher.getStateManager().setCurrentAnimation(anim); 将这个 AnimatorSet 注册给状态管理器,通常意味着 Launcher 会开始或已经处于 BACKGROUND_APP 状态。
      • 创建窗口动画 (getOpeningWindowAnimators): 这是最核心的部分,负责应用窗口从无到有、从小到大的动画:
        • 创建 FloatingIconView: 调用 FloatingIconView.getFloatingIconView(...),根据点击的图标 v 创建一个悬浮的、可变形的图标视图,并计算出它在 DragLayer 中的初始边界 (launcherIconBounds)。原始图标通常会被隐藏。
        • 计算动画参数 (AnimOpenProperties): 计算出动画所需的详细起止参数,包括:窗口裁剪区域 (从图标大小到全屏)、窗口位置/缩放 (从图标位置/大小到全屏)、浮动图标的位置/缩放 (与窗口同步)、浮动图标与窗口的 Alpha 透明度变化(浮动图标淡出、窗口淡入)、窗口圆角(从图标圆角到系统窗口圆角)、阴影等。
        • 创建主驱动动画 (ValueAnimator): 创建一个从 0 到 1 的 ValueAnimator,时长为 APP_LAUNCH_DURATION,使用 LINEAR 插值器,它驱动整个动画的进度。
        • 添加更新监听器 (MultiValueUpdateListener): 这是每一帧执行变换的地方:
          • 使用多个 FloatProp 实例(带有不同的插值器如 mOpeningXInterpolator, mOpeningInterpolator)根据主进度计算当前帧的精确属性值(位移 dX, dY,缩放 mIconScaleToFitScreen,Alpha mIconAlpha,窗口圆角 mWindowRadius,窗口裁剪 mCropRect* 等)。
          • 更新 FloatingIconView: 调用 floatingView.update(...),传入计算好的边界、Alpha、形状进度、圆角等,让浮动图标在视觉上匹配正在变化的“窗口”。
          • 应用 SurfaceControl.Transaction: 创建一个 SurfaceControl.Transaction。遍历 appTargets,对于 MODE_OPENING 的 Target (即正在打开的应用窗口):
            • 获取其 SurfaceControl (Leash)。
            • 计算 Matrix 来设置缩放和位移。
            • 调用 transaction.forSurface(target.leash) 获取 Surface 属性构建器。
            • 使用 .setMatrix(), .setWindowCrop(), .setAlpha() (通常是 1f - mIconAlpha.value,实现交叉淡入淡出), .setCornerRadius(), .setShadowRadius() 等方法设置当前帧的窗口属性。
          • 应用 Transaction: 调用 surfaceApplier.scheduleApply(transaction) 将这一帧的所有 Surface 变换提交给 SurfaceFlinger
        • 添加清理监听器:appAnimator 上添加 AnimatorListenerAdapter,在 onAnimationEnd 时释放 RemoteAnimationTarget (openingTargets.release()) 并可能恢复图标状态。
      • 创建 Launcher 内容退场动画 (getLauncherContentAnimator): 创建另一个 AnimatorSet 来并行地动画 Launcher 自身的 UI 元素(Workspace, Hotseat, QSB, ScrimView 等),通常是让它们缩小、淡出。源码显示它会根据 Launcher 当前状态 (ALL_APPS, OVERVIEW, NORMAL) 选择不同的元素和方式进行动画。如果 ENABLE_SCRIM_FOR_APP_LAUNCH 开启,还会动画 ScrimView 的背景色。
      • 组合动画: 将窗口动画 (getOpeningWindowAnimators 返回的) 和 Launcher 内容动画 (getLauncherContentAnimator 返回的) 添加到主 AnimatorSet (anim) 中,使它们协同播放。
      • 添加 JANK 追踪: 使用 addCujInstrumentation 添加卡顿监控。
      • 设置 Launcher 不可见: 如果 Launcher 窗口本身是 MODE_CLOSING Target,添加 mForceInvisibleListener,在动画期间强制 Launcher 视图不可见 (INVISIBLE_BY_APP_TRANSITIONS)。
    • 返回结果: AppLaunchAnimationRunner 通过 AnimationResult.setAnimation(...) 将构建好的主 AnimatorSet 返回给系统。
  5. 动画结束与清理 (不变):

    • 系统播放 AnimatorSet。动画结束时,onAnimationEnd 监听器被调用。
    • 清理 FloatingIconView,释放 SurfaceControl 资源,执行 mOnEndCallback 中的回调,Launcher 状态稳定在 BACKGROUND_APP。应用窗口完全可见并获得焦点。

总结:

QuickstepTransitionManager 通过其内部类 AppLaunchAnimationRunner 精确地实现了图标到应用的启动动画。核心在于 composeIconLaunchAnimator 方法,它协同了以下几个关键部分:

  1. FloatingIconView: 提供图标变形放大的视觉引导。
  2. SurfaceControl.Transaction: 在动画每一帧直接操控打开应用的窗口 Surface (Leash),改变其 Matrix (位置/缩放)、Crop、Alpha、圆角等属性,使其从模拟图标状态平滑过渡到全屏状态。
  3. getLauncherContentAnimator: 并行地将 Launcher 的 Workspace、Hotseat 等内容动画隐藏。
  4. StateManager: 将此动画与 Launcher 内部状态(通常是进入 BACKGROUND_APP)关联起来。

整个过程充分利用了远程动画和 SurfaceControl 的能力,实现了高性能、跨进程、视觉效果丰富且同步精确的启动过渡。

相关文章:

AOSP Android14 Launcher3——点击桌面图标启动应用动画流程

在Launcher3中,点击桌面应用图标时,会有一个从 图标位置起始到全屏的动画过程,使得应用的打开过程不是生硬的启动过程。 这个动画具体是怎么实现的呢?本文对这个过程进行一个梳理 在Launcher中,动画大体上可以分为两类…...

windows端远程控制ubuntu运行脚本程序并转发ubuntu端脚本输出的网页

背景 对于一些只能在ubuntu上运行的脚本,并且这个脚本会在ubuntu上通过网页展示运行结果。我们希望可以使用windows远程操控ubuntu,在windows上查看网页内容。 方法 start cmd.exe /k "sshpass -p passwd ssh namexxx.xxx.xxx.xxx "cd /hom…...

【官方正版,永久免费】Adobe Camera Raw 17.2 win/Mac版本 配合Adobe22-25系列软

Adobe Camera Raw 2025 年 2 月版(版本 17.2)。目前为止最新版新版已经更新2个月了,我看论坛之前分享的还是2024版,遂将新版分享给各位。 Adobe Camera Raw,支持Photoshop,lightroom等Adobe系列软件&#…...

如何使用flatten函数在Terraform 中迭代嵌套map

简介 flatten 接受一个列表,并用列表内容的扁平序列替换列表中的任何元素。 > flatten([["a", "b"], [], ["c"]]) ["a", "b", "c"] > flatten([[["a", "b"], []], [&quo…...

原生 HTML 的`title` 属性修改触发事件为鼠标移入移出显示

HTML中title属性的适用范围 在 HTML 中,title 属性是全局属性(Global Attribute),这意味着它可以被应用到所有 HTML 标签上。无论是块级元素(如 <div>)、行内元素(如 <span>),还是表单元素(如 <input>),都可以添加 title 属性。 常见使用 title…...

【论文精读】Reformer:高效Transformer如何突破长序列处理瓶颈?

目录 一、引言&#xff1a;当Transformer遇到长序列瓶颈二、核心技术解析&#xff1a;从暴力计算到智能优化1. 局部敏感哈希注意力&#xff08;LSH Attention&#xff09;&#xff1a;用“聚类筛选”替代“全量计算”关键步骤&#xff1a;数学优化&#xff1a; 2. 可逆残差网络…...

jmeter中监控服务器ServerAgent

插件下载&#xff1a; 将ServerAgent上传至需要监控的服务器&#xff0c;mac/liunx启动startAgent.sh&#xff08;启动命令&#xff1a;./startAgent.sh&#xff09; 在jmeter中添加permon监控组件 配置需要监控的服务器IP地址&#xff0c;添加需要监控的资源 注意&#xf…...

网络结构及安全科普

文章目录 终端联网网络硬件基础网络协议示例&#xff1a;用户访问网页 OSI七层模型网络攻击&#xff08;Hack&#xff09;网络攻击的主要类别&#xff08;一&#xff09;按攻击目标分类&#xff08;二&#xff09;按攻击技术分类 网络安全防御 典型攻击案例相关名词介绍网络连接…...

JVM虚拟机-JVM调优、内存泄漏排查、CPU飙高排查

一、JVM调优的参数在哪里设置 项目开发过程中有以下两种部署项目的方式&#xff1a; 项目部署在tomcat中&#xff0c;是一个war包&#xff1b;项目部署在SpringBoot中&#xff0c;是一个jar包。 (1)war包 catalina文件在Linux系统下的tomcat是以sh结尾&#xff0c;在windows系…...

安全复健|windows常见取证工具

写在前面&#xff1a; 此博客仅用于记录个人学习内容&#xff0c;学识浅薄&#xff0c;若有错误观点欢迎评论区指出。欢迎各位前来交流。&#xff08;部分材料来源网络&#xff0c;若有侵权&#xff0c;立即删除&#xff09; 取证 01系统运行数据 使用工具&#xff1a;Live-F…...

FPGA开发流程初识

FPGA 的开发流程可知&#xff0c;在 FPGA 开发的过程中会产生很多不同功能的文件&#xff0c;为了方便随时查找到对应文件&#xff0c;所以在开始开发设计之前&#xff0c;我们第一个需要考虑的问题是工程内部各种文件的管理。如 果不进行文件分类&#xff0c;而是将所有文件…...

Docker 中将文件映射到 Linux 宿主机

在 Docker 中&#xff0c;有多种方式可以将文件映射到 Linux 宿主机&#xff0c;以下是常见的几种方法&#xff1a; 使用-v参数• 基本语法&#xff1a;docker run -v [宿主机文件路径]:[容器内文件路径] 容器名称• 示例&#xff1a;docker run -it -v /home/user/myfile.txt:…...

C# 类型、存储和变量(栈和堆)

本章内容 C#程序是一组类型声明 类型是一种模板 实例化类型 数据成员和函数成员 预定义类型 用户定义类型 栈和堆 值类型和引用类型 变量 静态类型和dynamic关键字 可空类型 栈和堆 程序运行时&#xff0c;它的数据必须存储在内存中。一个数据项需要多大的内存、存储在什么地方…...

基于深度学习Yolo8的驾驶员疲劳与分心行为检测系统

基于深度学习Yolo8的驾驶员疲劳与分心行为检测系统 【包含内容】 【一】项目提供完整源代码及详细注释 【二】系统设计思路与实现说明 【三】疲劳检测模型与行为分析统计 【技术栈】 ①&#xff1a;系统环境&#xff1a;Windows/Mac/Linux ②&#xff1a;开发环境&#xff1a;P…...

AOSP Android14 Launcher3——远程窗口动画关键类SurfaceControl详解

在 Launcher3 执行涉及其他应用窗口&#xff08;即“远程窗口”&#xff09;的动画时&#xff0c;例如“点击桌面图标启动应用”或“从应用上滑回到桌面”的过渡动画&#xff0c;SurfaceControl 扮演着至关重要的角色。它是实现这些跨进程、高性能、精确定制动画的核心技术。 …...

Linux系统学习----概述与目录结构

linux 是一个开源、免费的操作系统&#xff0c;其稳定性、安全性、处理多并发已经得到业界的认可&#xff0c;目前很多企业级的项目 (c/c/php/python/java/go)都会部署到 Linux/unix 系统上。 一、虚拟机系统操作 1.网络连接的三种方式&#xff08;桥接模式、nat模式、主机模…...

python pdf转图片再OCR

先pdf转图片 import os from pdf2image import convert_from_path# PDF文件路径 pdf_path /Users/xxx/2022.pdf # 输出图片的文件夹 output_folder ./output_images2022 # 输出图片的命名格式 output_name page# 如果输出文件夹不存在&#xff0c;创建它 if not os.path.ex…...

(2)Docker 常用命令

文章目录 Docker 服务器Docker 镜像Docker 容器本地 RegistryRUN vs CMD vs ENTRYPOINTRUNCMDENTRYPOINT 限制容器对内存、CPU 和 IO 资源的使用内存CPUBlock IO设置权重bps 和 iops cgroup 和 namespacecgroupnamespacMount namespaceUTS namespaceIPC namespacePID namespace…...

虚拟列表技术深度解析:原理、实现与性能优化实战

虚拟列表技术深度解析&#xff1a;原理、实现与性能优化实战 引言 在当今数据驱动的互联网应用中&#xff0c;长列表渲染已成为前端开发的核心挑战。传统的一次性全量渲染方式在数据量超过千条时&#xff0c;往往导致页面卡顿、内存飙升等问题。虚拟列表&#xff08;Virtual L…...

服务器简介(含硬件外观接口介绍)

服务器&#xff08;Server&#xff09;是指提供资源、服务、数据或应用程序的计算机系统或设备。它通常比普通的个人计算机更强大、更可靠&#xff0c;能够长时间无间断运行&#xff0c;支持多个用户或客户端的请求。简单来说&#xff0c;服务器就是专门用来存储、管理和提供数…...

c++下的onnx推理

参考代码&#xff1a;https://github.com/itsnine/yolov5-onnxruntime 参考链接&#xff1a;https://blog.csdn.net/magic_ll/article/details/125517798 1.下载onnx 官网&#xff1a;https://github.com/microsoft/onnxruntime/releases/tag/v1.21.0 2.下载代码 https://g…...

TCP三次握手与四次挥手面试回答版本

面试官&#xff1a;说一下TCP三次握手的过程 参考面试回答&#xff1a; 在第一次握手的时候、客户端会随机生成初始化序号、放到TCP报文头部的序号字段中、同时把SYN标志设置为1 这样就表示SYN报文&#xff08;这里是请求报文&#xff09;。客户端将报文放入 TCP 报文首部的序…...

Vue3 使用PrimeVue的面包屑组件Breadcrumb,使用JS滚动进行

做了一个自动添加的面包写导航栏&#xff0c;需要在添加之后自动滚动到最右边&#xff0c;发现常规的滚动方法不行&#xff0c;以下是源码&#xff0c;直接调用ScrollToRight方法就行&#xff0c;最主要的就是在value后面加一个$el&#xff1a; <Breadcrumb :home"hom…...

0101基础知识-区块链-web3

文章目录 1 web3学习路线2 区块链简史2.1 区块链2.2 公共账本2.3 区块链的设计哲学2.3.1 去中心化2.3.2 共识2.3.2.1 上链2.3.2.2 共识算法 3 web3面向资产的互联网3.1 安全性和去中心化的权衡 4 智能合约4.1 以太坊智能合约4.2 去中心化应用 5 小结结语 1 web3学习路线 参考下…...

工作纪实_63-Mac电脑使用brew安装软件

最近在接触kafka&#xff0c;想着在自己的电脑安装一套环境&#xff0c;docker也能行&#xff0c;但是还是想装一些原生的软件试试看&#xff0c;因此便想着整理一下brew的命令&#xff0c;这命令确实是方便&#xff0c;不需要下载tar包乱八七糟的东西&#xff0c;一键安装 bre…...

Cadence学习笔记之---库元件制作、元件放置

目录 01 | 引 言 02 | 环境描述 03 | 工具介绍 04 | 无源器件的制作 05 | IC芯片制作 06 | 放置元件 07 | 结 语 01 | 引 言 在上一篇小记中&#xff0c;讲述使用Cadence创建原理图工程和元件库&#xff1b; 本篇小记主要讲述如何制作常用的库元件&#xff0c;如电阻、…...

服务器如何修复SSL证书错误?

修复服务器上的SSL证书错误需要根据具体错误类型逐步排查和解决。以下是常见的步骤和解决方案&#xff1a; --- ### **1. 确认错误类型** 首先检查浏览器或工具&#xff08;如OpenSSL&#xff09;报错的具体信息&#xff0c;常见错误包括&#xff1a; - **证书过期**&#xf…...

图解Mysql原理:深入理解事务的特性以及它的实现机制

前言 大家好&#xff0c;我是程序蛇玩编程。 Mysql中事务大家不陌生吧&#xff0c;事务就是要保证一组数据库操作&#xff0c;要么全部成功&#xff0c;要么全部失败。那它具有哪些特性&#xff0c;如何实现的呢?接着往下看。 正文 事务的特性: 事务的基本特性主要为四种…...

《前端面试题之 Vue 篇(第四集)》

目录 1、Vue 中实现强制刷新2、Vue3 和 Vue2 的区别解析3、 Vue3 性能优于 Vue2 的原因解析4、Vue3 使用 Proxy5、首屏优化6、组件的理解7、vue项目中合理规划文件目录8、Nuxt.js 简单了解9、单页应用10、 SEO 优化 1、Vue 中实现强制刷新 在 Vue 中实现强制刷新的分析如下&am…...

C++ 模块化编程(Modules)在大规模系统中的实践难点

随着项目规模的不断扩大和代码复杂性的提升,传统的 C++ 开发模式逐渐暴露出一些根深蒂固的问题,尤其是头文件和预处理器机制所带来的编译效率低下、依赖管理混乱以及代码复用性差等痛点。C++20 标准引入的模块化编程(Modules)特性,正是为了解决这些问题而设计的一项革命性…...