AOSP14 Launcher3——最近任务TaskViewSimulator详解
前言:TaskViewSimulator 这个类在最近任务中起到了一个非常重要的作用。
从字面意思上理解,这个单词是由TaskView+Simulator组合而来,字面意思就是TaskView的模拟器,顾名思义,就是一个用来模拟TaskView的类。
为什么要模拟TaskView呢?这个类跟TaskView本身又有什么关系和区别呢?本文来详解一下这个类。
我们来详细解释一下 quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
这个类的作用。
核心作用 (Core Purpose):
TaskViewSimulator
的核心作用是模拟(Simulate)一个应用窗口(由 RemoteAnimationTarget
代表,本质是一个 SurfaceControl
Leash)在手势导航过程中,从全屏状态过渡到最近任务(RecentsView)中的任务卡片(TaskView)外观所需的视觉变换(Visual Transformation)。
简单来说,当你在屏幕底部上滑时,你看到的那个正在缩小的应用窗口,它的大小、位置、裁剪区域、圆角等视觉属性,并不是直接由 RecentsView 里的 TaskView 控制的,而是由 TaskViewSimulator
计算出来,然后应用到系统层级的应用窗口 Leash 上的。它扮演了一个**“虚拟 TaskView 布局计算器”**的角色。
为什么需要模拟?(Why Simulation is Needed):
- 解耦 (Decoupling): 最近任务动画是由 SystemUI (WindowManager/Shell) 发起的,它控制的是应用窗口的真实 Surface。而
RecentsView
和TaskView
是 Launcher 应用内部的 UI 组件。直接让 Launcher 的 View 去控制系统级的 Surface 是不合适的,也存在进程间通信的复杂性。 - 性能 (Performance): 在手势进行的每一帧,直接操作和重新布局 Launcher 的
RecentsView
和TaskView
来匹配窗口动画,开销会非常大。模拟计算变换参数然后应用到 Surface 上效率更高。 - 精确匹配 (Exact Matching):
TaskViewSimulator
通过模拟RecentsView
和TaskView
的布局逻辑(包括滚动、缩放、全屏进度等),确保应用窗口 Leash 的视觉效果能精确地匹配用户在RecentsView
中看到的卡片位置和外观,实现无缝过渡。
主要功能和协调方式 (Key Functions and Coordination):
-
接收输入参数 (Receiving Inputs):
- 目标信息 (
setPreview
,setPreviewBounds
): 接收RemoteAnimationTarget
,从中获取应用窗口的初始边界 (startBounds
/screenSpaceBounds
) 和内容边距 (contentInsets
)。这是模拟的“起点”。 - 布局环境 (
setDp
,setOrientationState
): 设置当前的DeviceProfile
(屏幕尺寸、密度、方向等) 和RecentsOrientedState
(处理不同屏幕方向下的布局)。这是计算目标布局的基础。 - 动画状态 (
AnimatedFloat
属性): 持有一系列AnimatedFloat
变量,如fullScreenProgress
(0=全屏, 1=概览)、recentsViewScale
(概览缩放)、recentsViewScroll
(概览滚动偏移)、taskPrimaryTranslation
等。这些变量通常由手势处理器(如AbsSwipeUpHandler
)根据用户的滑动距离和速度来更新,代表了当前动画的进度。 - 分屏信息 (
setPreview(..., SplitBounds)
): 如果是分屏模式,接收分屏布局信息。
- 目标信息 (
-
模拟计算 (Simulation Calculation):
getFullScreenScale()
: 计算当应用窗口完全进入 RecentsView 时的目标缩放比例和缩放中心点 (mPivot
)。这个计算考虑了DeviceProfile
和任务卡片的标准尺寸。apply(TransformParams params)
: 这是核心计算方法。它在每一帧动画更新时被调用:- 检查布局是否有效 (
mLayoutValid
),如果设备配置或方向状态改变,则重新计算基础布局(如任务卡片在 RecentsView 中的目标位置mTaskRect
,缩略图变换矩阵mPositionHelper
)。 - 获取当前所有
AnimatedFloat
输入的值(进度、滚动、缩放等)。 - 结合
mPositionHelper
(模拟缩略图定位)、mTaskRect
(模拟卡片目标位置)、mPivot
(缩放中心)以及各种平移和缩放值,计算出一个最终的变换矩阵 (mMatrix
)。这个矩阵描述了如何将原始的应用窗口内容变换到当前模拟的 TaskView 外观。 - 计算应用窗口应该被裁剪的区域 (
mTmpCropRect
),使得只有模拟 TaskView 的部分可见。 - 计算应用窗口应该应用的圆角半径 (
getCurrentCornerRadius()
),使其匹配 TaskView 的圆角。
- 检查布局是否有效 (
onBuildTargetParams(...)
: 实现TransformParams.BuilderProxy
接口,将apply()
方法计算出的mMatrix
,mTmpCropRect
,getCurrentCornerRadius()
以及可能的层级顺序 (setLayer
) 填充到SurfaceProperties
对象中。
-
输出变换参数 (Outputting Transform Parameters):
TaskViewSimulator
本身不直接操作 Surface。它的计算结果(Matrix, Crop, Corner Radius)会通过TransformParams
对象传递出去。- 调用者(通常是
AbsSwipeUpHandler
或其创建的动画类)会获取这些参数,并使用SurfaceControl.Transaction
将这些变换应用到RemoteAnimationTarget
对应的真实应用窗口 Leash 上。
协调关系总结:
AbsSwipeUpHandler
(或其他手势/动画控制器):- 根据用户手势更新
TaskViewSimulator
的AnimatedFloat
输入值 (进度、滚动等)。 - 调用
TaskViewSimulator.apply(params)
来获取计算出的变换参数。 - 将获取到的参数应用到实际的
SurfaceControl
Leash。
- 根据用户手势更新
RecentsView
:- 其布局逻辑(如卡片大小、间距、滚动行为)被
TaskViewSimulator
模拟。 - 当
RecentsView
滚动时,其滚动偏移量会作为输入 (recentsViewScroll.value
) 提供给TaskViewSimulator
,用于计算窗口的横向/纵向跟随移动。
- 其布局逻辑(如卡片大小、间距、滚动行为)被
RemoteAnimationTarget
:- 提供了
TaskViewSimulator
需要模拟的原始窗口信息(Leash、初始Bounds、Insets)。 - 是
TaskViewSimulator
计算结果的最终应用对象。
- 提供了
总之,TaskViewSimulator
是一个关键的转换器和计算引擎。它将手势进度和 RecentsView 的布局状态,转换为对系统级应用窗口 Surface 的精确视觉控制参数,从而实现了从全屏应用到 RecentsView 卡片的流畅、视觉一致的动画效果。