AOSP14 Launcher3——手势上滑关键类AbsSwipeHandler解析
我们来深入分析 quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java 这个非常核心且复杂的类。
1. 核心作用 (Core Role):
AbsSwipeUpHandler 是 Quickstep (Launcher3 的手势导航实现) 中处理从屏幕底部上滑手势的核心逻辑抽象基类。它负责管理从手势开始到结束的整个流程,包括:
- 手势识别与处理: 接收原始触摸事件,计算滑动距离、速度和方向。
- 窗口动画控制: 连接并控制由 SystemUI 提供的
RecentsAnimationController,通过操作应用窗口和 Launcher 窗口的 Surface (Leash),实现平滑的过渡动画(应用 <-> Launcher/概览)。 - 界面状态同步: 协调 Launcher UI 元素(如 Workspace、Hotseat、RecentsView)的状态和动画,使其与手势进度和窗口动画保持同步。
- 目标状态决策: 根据手势的速度、距离、暂停状态以及用户在 RecentsView 中的交互,计算手势的最终目标(
GestureEndTarget):返回桌面 (HOME)、进入概览/最近任务 (RECENTS)、切换到上一个应用 (LAST_TASK)、切换到新任务 (NEW_TASK) 或进入所有应用列表 (ALL_APPS)。 - 动画执行与收尾: 启动并管理过渡到最终目标状态的动画,并在动画结束后释放资源、完成任务切换或返回桌面。
- 处理特殊情况: 如 PiP (画中画) 窗口的特殊动画、分屏模式、Taskbar 交互等。
简单来说,它是连接用户上滑手势输入、系统窗口动画控制以及 Launcher UI 状态变化的总指挥。
2. 如何协调其他类 (Coordination):
AbsSwipeUpHandler 像一个交响乐指挥,协调多个组件共同完成复杂的动画和状态切换:
GestureState:- 提供者: 外部(如
TouchInteractionService)创建并传入。 - 交互:
AbsSwipeUpHandler从GestureState读取手势信息(起始点、当前运行任务、速度、是否暂停等),并将计算出的最终目标 (endTarget) 写回GestureState。
- 提供者: 外部(如
RecentsAnimationController&RecentsAnimationTargets:- 提供者: 由 SystemUI (WindowManager) 在手势开始时通过
onRecentsAnimationStart回调提供。 - 交互:
AbsSwipeUpHandler使用RecentsAnimationController来:- 获取和控制应用/Launcher 窗口的 Surface Leash。
- 截取任务快照 (
screenshotTask)。 - 设置 SystemUI 标志(如状态栏/导航栏外观)。
- 最终结束动画 (
finish()),将控制权交还给系统。
RecentsAnimationTargets提供了动画目标的详细信息(如 TaskInfo, Leash, 初始位置等)。
- 提供者: 由 SystemUI (WindowManager) 在手势开始时通过
TaskViewSimulator&RemoteTargetHandle&RemoteTargetGluer:- 交互:
AbsSwipeUpHandler通过RemoteTargetGluer将RecentsAnimationTargets分配给一个或多个RemoteTargetHandle。每个RemoteTargetHandle包含一个TaskViewSimulator。 TaskViewSimulator至关重要,它负责计算应用窗口 Leash 的变换(Translation, Scale, Alpha, Crop, Corner Radius)。AbsSwipeUpHandler在applyScrollAndTransform方法中,根据当前手势进度 (mCurrentShift.value) 和RecentsView的滚动偏移,更新TaskViewSimulator的状态,并应用这些变换到实际的 Surface Leash 上。
- 交互:
StatefulActivity(e.g.,QuickstepLauncher) &BaseActivityInterface:- 交互: 通过
mActivityInterface与 Launcher Activity 交互:- 获取 Activity 实例 (
getCreatedActivity())。 - 获取核心 UI 组件,特别是
RecentsView(getOverviewPanel())。 - 准备 Recents UI (
prepareRecentsUI),这通常会返回一个AnimationFactory,用于创建 Launcher 内部元素的动画控制器 (mLauncherTransitionController)。 - 通知 Activity 手势结束并即将返回桌面 (
onSwipeUpToHomeComplete) 或切换任务失败 (onLaunchTaskFailed)。 - 获取
DeviceProfile和其他配置信息。
- 获取 Activity 实例 (
- 交互: 通过
RecentsView(e.g.,LauncherRecentsView):- 交互:
- 在手势开始时通知
RecentsView(onGestureAnimationStart),让它可以准备任务卡片。 - 链接滚动事件 (
linkRecentsViewScroll,mOnRecentsScrollListener):当RecentsView滚动时,会触发onRecentsViewScroll,进而调用applyScrollAndTransform来更新应用窗口的位置,实现窗口跟随卡片滚动的效果。 - 获取当前/目标页面 (
getCurrentPage,getNextPage) 和对应的TaskView,用于判断手势目标和启动任务。 - 在手势结束动画开始时,让
RecentsView参与动画 (onPrepareGestureEndAnimation)。 - 在手势结束动画完成后,通知
RecentsView(onSwipeUpAnimationSuccess或onGestureAnimationEnd)。 - 更新任务缩略图 (
updateThumbnail)。
- 在手势开始时通知
- 交互:
MultiStateCallback(mStateCallback):- 作用: 这是
AbsSwipeUpHandler内部管理异步流程的关键机制。手势涉及多个异步事件(Launcher 启动、绘制完成、动画控制器接收、截图完成、手势完成等)。mStateCallback定义了一系列状态标志 (STATE_*)。 - 交互: 通过
mStateCallback.setStateOnUiThread()设置状态,通过mStateCallback.runOnceAtState(STATE_FLAGS, runnable)注册回调。只有当所有指定的状态标志位都变为 1 时,对应的runnable才会被执行。这确保了操作在正确的时机发生,避免了复杂的嵌套回调和竞态条件。
- 作用: 这是
AnimatorControllerWithResistance(mLauncherTransitionController):- 作用: 控制 Launcher 内部 UI 元素的动画(例如 Hotseat 的淡出、Workspace 的缩放)。
- 交互: 由
AnimationFactory(通过mActivityInterface.prepareRecentsUI获得) 创建。AbsSwipeUpHandler在onCurrentShiftUpdated中根据手势进度 (mCurrentShift.value) 更新这个控制器的进度,驱动 Launcher UI 的过渡效果。
HomeAnimationFactory(由子类实现):- 作用: 定义了当手势目标是
HOME时,窗口如何具体地动画到桌面上(例如,缩小到图标、缩小到小部件、或者仅仅是淡出)。 - 交互:
AbsSwipeUpHandler在确定目标是HOME时,会调用子类实现的createHomeAnimationFactory来获取具体的动画逻辑,并执行它。
- 作用: 定义了当手势目标是
InputConsumerProxy:- 作用: 在手势进行到特定阶段(例如,确定要进入 Launcher 状态时)启用,拦截原本会传递给下方应用窗口的触摸事件,确保手势能继续控制 Launcher UI。
3. 手势与最近任务动画流程示例 (Simplified Flow):
- 手势开始: 用户从底部上滑。
TouchInteractionService检测到手势,创建AbsSwipeUpHandler实例。 - 系统动画启动: SystemUI 启动 Recents 动画,调用
onRecentsAnimationStart,提供controller和targets。 - Launcher 准备:
AbsSwipeUpHandler通过mActivityInitListener等待 Launcher Activity (mActivity) 准备好。onActivityInit获取mRecentsView引用。prepareRecentsUI被调用,mLauncherTransitionController被创建。 - 手势进行中:
- 用户手指移动,
updateDisplacement计算出手势进度mCurrentShift.value。 onCurrentShiftUpdated被调用。applyScrollAndTransform使用TaskViewSimulator更新应用窗口 Leash 的变换(缩放、平移等)。mLauncherTransitionController.setProgress更新 Launcher 内部 UI 动画。- 如果用户在
RecentsView上左右滑动,onRecentsViewScroll会触发,同样调用applyScrollAndTransform使窗口跟随移动。
- 用户手指移动,
- 手势结束: 用户抬起手指。
onGestureEnded被调用。 - 目标计算:
calculateEndTarget根据速度、位置、是否暂停等因素,决定最终去向(HOME,RECENTS,LAST_TASK等)。 - 结束动画:
handleNormalGestureEnd->animateToProgressInternal启动收尾动画。- 去 HOME: 调用
createHomeAnimationFactory,启动特定的回家动画(可能是RectFSpringAnim驱动窗口缩小到图标/小部件)。 - 去 RECENTS/LAST_TASK: 启动
ValueAnimator平滑过渡mCurrentShift.value到 0 或 1,同时可能驱动RecentsView滚动到目标页面。
- 动画完成 & 状态同步: 动画结束监听器触发
onSettledOnEndTarget。 - 最终操作: 根据
endTarget:- HOME/RECENTS: 调用
mRecentsAnimationController.finish(true/false, ...)通知系统结束动画,释放 Leash 控制。 - LAST_TASK: 调用
mRecentsAnimationController.finish(false, ...)恢复上一个任务。 - NEW_TASK: 调用
startNewTask启动RecentsView中选中的任务。
- HOME/RECENTS: 调用
- 清理:
reset被调用,清理状态和监听器,准备下一次手势。
AbsSwipeUpHandler 通过精密的事件监听、状态管理和对系统动画 API 及 Launcher 内部组件的协调,实现了复杂而流畅的手势导航体验。它的抽象设计允许子类(如 LauncherSwipeHandlerV2)定制特定的回家动画逻辑。
相关文章:
AOSP14 Launcher3——手势上滑关键类AbsSwipeHandler解析
我们来深入分析 quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java 这个非常核心且复杂的类。 1. 核心作用 (Core Role): AbsSwipeUpHandler 是 Quickstep (Launcher3 的手势导航实现) 中处理从屏幕底部上滑手势的核心逻辑抽象基类。它负责管理从手势开始到结束的…...
设计模式——建造者模式(生成器模式)总结
当我们需要创建一个非常复杂的对象时,可以使用建造者模式,分步骤建造一个对象,最后将完整的对象返回给客户端。 比如,我们要生成一个房子对象,建造一个房子,需要打地基、盖围墙、盖地板、安装门、安装窗户…...
Spring Boot(二十一):RedisTemplate的String和Hash类型操作
RedisTemplate和StringRedisTemplate的系列文章详见: Spring Boot(十七):集成和使用Redis Spring Boot(十八):RedisTemplate和StringRedisTemplate Spring Boot(十九)…...
使用Python爬虫的2大原因和6大常用库
爬虫其实就是请求http、解析网页、存储数据的过程,并非高深的技术,但凡是编程语言都能做,连Excel VBA都可以实现爬虫,但Python爬虫的使用频率最高、场景最广。 这可不仅仅是因为Python有众多爬虫和数据处理库,还有一个…...
Java 架构设计:从单体架构到微服务的转型之路
Java 架构设计:从单体架构到微服务的转型之路 在现代软件开发中,架构设计的选择对系统的可扩展性、可维护性和性能有着深远的影响。随着业务需求的日益复杂和用户规模的不断增长,传统的单体架构逐渐暴露出其局限性,而微服务架构作…...
C# 混淆代码工具--ConfuserEx功能与使用指南
目录 1 前言1.1 可能带来的问题 2 ConfuserEx2.1 简介2.2 功能特点2.3 基本使用方法2.4 集成到MSBuild2.5 深入设置2.5.1 保护机制2.5.1.1 ConfuserEx Protection 2.5.2 精细的代码保护主要特性1. decl-type(string)2.full-name(string)3. is-public()4. match(string)5. match…...
使用PyTorch实现目标检测边界框转换与可视化
一、引言 在目标检测任务中,边界框(Bounding Box)的坐标表示与转换是核心基础操作。本文将演示如何: 实现边界框的两种表示形式(角点坐标 vs 中心坐标)之间的转换 使用Matplotlib在图像上可视化边界框 验…...
nlp面试重点
深度学习基本原理:梯度下降公式,将损失函数越来越小,最终预测值和实际值误差比较小。 交叉熵:-p(x)logq(x),p(x)是one-hot形式。如果不使用softmax计算交叉熵,是不行的。损失函数可能会非常大,…...
欢乐力扣:反转链表二
文章目录 1、题目描述2、思路 1、题目描述 反转链表二。 给你单链表的头指针 head 和两个整数 left 和 right ,其中 left < right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。 2、思路 参考官方题解,基本思路…...
2025最新系统 Git 教程(七)(完结)
第4章 分布式Git 4.1 分布式 Git - 分布式工作流程 你现在拥有了一个远程 Git 版本库,能为所有开发者共享代码提供服务,在一个本地工作流程下,你也已经熟悉了基本 Git 命令。你现在可以学习如何利用 Git 提供的一些分布式工作流程了。 这一…...
14-大模型微调和训练之-Hugging Face 模型微调训练(基于 BERT 的中文评价情感分析(二分类))
1. datasets 库核心方法 1.1. 列出数据集 使用 datasets 库,你可以轻松列出所有 Hugging Face 平台上的数据集: from datasets import list_datasets # 列出所有数据集 all_datasets list_datasets() print(all_datasets)1.2. 加载数据集 你可以通过…...
聊透多线程编程-线程基础-4.C# Thread 子线程执行完成后通知主线程执行特定动作
在多线程编程中,线程之间的同步和通信是一个常见的需求。例如,我们可能需要一个子线程完成某些任务后通知主线程,并由主线程执行特定的动作。本文将基于一个示例程序,详细讲解如何使用 AutoResetEvent 来实现这种场景。 示例代码…...
论文阅读笔记——Reactive Diffusion Policy
RDP 论文 通过 AR 提供实时触觉/力反馈;慢速扩散策略,用于预测低频潜在空间中的高层动作分块;快速非对称分词器实现闭环反馈控制。 ACT、 π 0 \pi_0 π0 采取了动作分块,在动作分块执行期间处于开环状态,无法及时响…...
ISIS协议(动态路由协议)
ISIS基础 基本概念 IS-IS(Intermediate System to Intermediate System,中间系统到中间系统)是ISO (International Organization for Standardization,国际标准化组织)为它的CLNP(ConnectionL…...
大数据(7.1)Kafka实时数据采集与分发的企业级实践:从架构设计到性能调优
目录 一、实时数据洪流下的技术突围1.1 行业需求演进曲线1.2 传统方案的技术瓶颈 二、Kafka实时架构设计精要2.1 生产者核心参数矩阵2.1.1 分区策略选择指南 2.2 消费者组智能负载均衡 三、实时数据管道实战案例3.1 电商大促实时看板3.2 工业物联网预测性维护 四、生产环境性能…...
UniApp 实现兼容 H5 和小程序的拖拽排序组件
如何使用 UniApp 实现一个兼容 H5 和小程序的 九宫格拖拽排序组件,实现思路和关键步骤。 一、完整效果图示例 H5端 小程序端 git地址 二、实现目标 支持拖动菜单项改变顺序拖拽过程实时预览移动位置拖拽松开后自动吸附回网格兼容 H5 和小程序平台 三、功能…...
C,C++,C#
C、C 和 C# 是三种不同的编程语言,虽然它们名称相似,但在设计目标、语法特性、运行环境和应用场景上有显著区别。以下是它们的核心区别: 1. 设计目标和历史 语言诞生时间设计目标特点C1972(贝尔实验室)面向过程&#…...
MySQL | 三大日志文件
Undo Log(回滚日志) 实现原理与分类 原理:Undo Log 记录的是数据修改前的旧值,通过这些旧值可以将数据恢复到修改之前的状态。它采用的是逻辑日志,即记录的是如何撤销操作,而不是物理数据的实际值。 分类…...
【网络协议】WebSocket讲解
目录 webSocket简介 连接原理解析: 客户端API 服务端API(java) 实战案例 (1)引入依赖 (2)编写服务端逻辑 (3)注册配置类 (4)前端连接 WebSocket 示例…...
啥是Spring,有什么用,既然收费,如何免费创建SpringBoot项目,依赖下载不下来的解决方法,解决99%问题!
一、啥是Spring,为啥选择它 我们平常说的Spring指的是Spring全家桶,我们为什么要选择Spring,看看官方的话: 意思就是:用这个东西,又快又好又安全,反正就是好处全占了,所以我们选择它…...
一天时间,我用AI(deepseek)做了一个配色网站
前言 最近在开发颜色搭配主题的相关H5和小程序,想到需要补充一个web网站,因此有了这篇文章。 一、确定需求 向AI要答案之前,一定要清楚自己想要做什么。如果你没有100%了解自己的需求,可以先让AI帮你理清逻辑和思路,…...
Day14:关于MySQL的索引——创、查、删
前言:先创建一个练习的数据库和数据 1.创建数据库并创建数据表的基本结构 -- 创建练习数据库 CREATE DATABASE index_practice; USE index_practice;-- 创建基础表(包含CREATE TABLE时创建索引) CREATE TABLE products (id INT PRIMARY KEY…...
Pytorch深度学习框架60天进阶学习计划 - 第41天:生成对抗网络进阶(二)
Pytorch深度学习框架60天进阶学习计划 - 第41天:生成对抗网络进阶(二) 7. 实现条件WGAN-GP # 训练条件WGAN-GP def train_conditional_wgan_gp():# 用于记录损失d_losses []g_losses []# 用于记录生成样本的多样性(通过类别分…...
Spring - 13 ( 11000 字 Spring 入门级教程 )
一: Spring AOP 备注:之前学习 Spring 学到 AOP 就去梳理之前学习的知识点了,后面因为各种原因导致 Spring AOP 的博客一直搁置。。。。。。下面开始正式的讲解。 学习完 Spring 的统一功能后,我们就进入了 Spring AOP 的学习。…...
Spring Cloud Alibaba微服务治理实战:Nacos+Sentinel深度解析
一、引言 在微服务架构中,服务发现、配置管理、流量控制是保障系统稳定性的核心问题。Spring Cloud Netflix 生态曾主导微服务解决方案,但其部分组件(如 Eureka、Hystrix)已进入维护模式。 Spring Cloud Alibaba 凭借 高性能、轻…...
设计模式之迭代器模式:遍历的艺术与实现
引言 迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供了一种顺序访问聚合对象中各个元素的方法,而又不暴露其底层实现。迭代器模式将遍历逻辑与聚合对象解耦,使得我们可以用统一的方式处理不同的集合结构。…...
红宝书第三十六讲:持续集成(CI)配置入门指南
红宝书第三十六讲:持续集成(CI)配置入门指南 资料取自《JavaScript高级程序设计(第5版)》。 查看总目录:红宝书学习大纲 一、什么是持续集成? 持续集成(CI)就像咖啡厅的…...
Java—HTML:3D形变
今天我要介绍的是在Java HTML中CSS的相关知识点内容之一:3D形变(3D变换)。该内容包含透视(属性:perspective),3D变换,3D变换函数以及案例演示, 接下来我将逐一介绍&…...
什么是音频预加重与去加重,预加重与去加重的原理是什么,在什么条件下会使用预加重与去加重?
音频预加重与去加重是音频处理中的两个重要概念,以下是对其原理及应用条件的详细介绍: 1、音频预加重与去加重的定义 预加重:在音频信号的发送端,对音频信号的高频部分进行提升,增加高频信号的幅度,使其在…...
免费下载 | 2025清华五道口:“十五五”金融规划研究白皮书
《2025清华五道口:“十五五”金融规划研究白皮书》的核心内容主要包括以下几个方面: 一、五年金融规划的重要功能与作用 凝聚共识:五年金融规划是国家金融发展的前瞻性谋划和战略性安排,通过广泛听取社会各界意见,凝…...
