在阅读源码研究从第三方应用回到桌面的过程中,接触到RectFSpringAnim这个类,确认这个类就是最终动画的实现类。因此对这个类的源码进行阅读分析。
本文来详细分析 quickstep/src/com/android/quickstep/util/RectFSpringAnim.java 这个类。
核心作用 (Core Purpose):
RectFSpringAnim 的核心作用是提供一个基于物理弹簧模型 (Spring Physics) 的动画机制,用于平滑地、带有物理惯性地将一个矩形 (RectF) 从起始状态 (位置和大小) 动画到目标状态 (位置和大小)。
它主要用于 QuickstepTransitionManager 中处理**应用窗口关闭(返回桌面)**时的动画,模拟窗口从全屏状态自然地、带有速度感地收缩并移动到其在 Launcher 上的对应图标或小部件位置的过程。
工作原理 (How it Works):
与传统的基于时间插值器 (Time Interpolator) 的动画(如 ValueAnimator, ObjectAnimator) 不同,RectFSpringAnim 使用的是 AndroidX DynamicAnimation 库中的 SpringAnimation 和自定义的 FlingSpringAnim。其原理是:
-
分离动画维度: 它并不直接动画
RectF的 left, top, right, bottom 四个值。而是将矩形的动画分解为三个独立的、但同时进行的物理模拟:- 水平中心 (
RECT_CENTER_X): 使用FlingSpringAnim控制矩形水平中心点 (centerX) 的动画。FlingSpringAnim结合了初始的抛掷 (Fling) 速度和最终稳定到目标值的弹簧 (Spring) 效果。 - 垂直位置 (
RECT_Y): 使用FlingSpringAnim控制矩形一个垂直参考点的动画。这个参考点由mTracking变量决定:TRACKING_TOP: 动画矩形的top值。TRACKING_BOTTOM: 动画矩形的bottom值。TRACKING_CENTER: 动画矩形的centerY值。
选择哪个参考点取决于动画的具体场景(例如,窗口是从屏幕上方移入还是下方移入,目标位置更靠近哪边)。
- 缩放进度 (
RECT_SCALE_PROGRESS): 使用标准的SpringAnimation控制一个从 0 到 1 的进度值 (mCurrentScaleProgress)。这个进度值随后被用来线性插值计算矩形当前的宽度和高度(从起始宽高到目标宽高)。
- 水平中心 (
-
物理参数: 每个维度的弹簧动画都由物理参数控制:
- Stiffness (刚度): 弹簧的“硬度”,影响回弹的速度和振荡频率。 (
mStiffnessX,mStiffnessY,mRectStiffness)。 - Damping Ratio (阻尼比): 控制振荡衰减的速度。值小于 1 会产生振荡,等于 1 是临界阻尼(最快到达且不振荡),大于 1 是过阻尼(缓慢到达)。(
mDampingX,mDampingY)。
- Stiffness (刚度): 弹簧的“硬度”,影响回弹的速度和振荡频率。 (
-
动画启动 (
start方法):- 接收一个初始速度 (
velocityPxPerMs),通常是用户手指离开屏幕时的速度。 - 对速度进行阻尼处理 (
OverScroll.dampedScroll),防止过大的速度导致动画过于剧烈或不自然。 - 根据起始/目标位置、阻尼后的速度、物理参数(刚度、阻尼比)创建并启动
RECT_CENTER_X和RECT_Y的FlingSpringAnim。 - 根据Y轴速度和物理参数创建并启动
RECT_SCALE_PROGRESS的SpringAnimation。 - 通知外部监听器动画开始。
- 接收一个初始速度 (
-
动画更新 (
onUpdate方法):- 当任何一个底层的
SpringAnimation或FlingSpringAnim更新其值时,会触发其对应FloatPropertyCompat的setValue方法,进而调用RectFSpringAnim的onUpdate()。 - 在
onUpdate()中:- 根据当前的
mCurrentScaleProgress插值计算出当前的宽度 (currentWidth) 和高度 (currentHeight)。 - 根据当前的
mCurrentCenterX,mCurrentY以及mTracking模式,结合计算出的currentWidth,currentHeight,重新构建出完整的mCurrentRect(当前的矩形状态)。例如,如果mTracking == TRACKING_TOP,则mCurrentRect.top = mCurrentY,mCurrentRect.bottom = mCurrentY + currentHeight。 - 遍历所有注册的
OnUpdateListener,调用它们的onUpdate(mCurrentRect, mCurrentScaleProgress)方法,将最新计算出的矩形状态和缩放进度传递出去。
- 根据当前的
- 当任何一个底层的
-
动画结束 (
maybeOnEnd方法):- 每个底层的弹簧动画结束后,会设置对应的结束标志 (
mRectXAnimEnded,mRectYAnimEnded,mRectScaleAnimEnded)。 maybeOnEnd()会检查是否所有三个动画都已结束。- 只有当全部结束后,才会通知外部的
Animator.AnimatorListener动画结束,并设置setCanRelease(true)(用于RemoteAnimationTargets的资源释放检查)。
- 每个底层的弹簧动画结束后,会设置对应的结束标志 (
-
配置 (
SpringConfig子类):- 提供了不同的配置类(
DefaultSpringConfig,TaskbarHotseatSpringConfig)来为不同的动画场景(如普通返回桌面 vs 返回到 Taskbar/Hotseat 上的图标)提供预设的、经过调整的物理参数(刚度、阻尼、追踪模式),以达到最佳的视觉效果。
- 提供了不同的配置类(
在 Launcher3 中的作用:
RectFSpringAnim 在 Launcher3 (Quickstep) 中扮演着一个特定场景下的动画引擎角色:
- 驱动窗口关闭动画: 它是
QuickstepTransitionManager在处理应用关闭返回桌面动画时的核心驱动力之一 (尤其是在createWallpaperOpenAnimations->getClosingWindowAnimators中被创建和使用)。
// 应用关闭返回桌面动画
//quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
protected RectFSpringAnim getClosingWindowAnimators(AnimatorSet animation,
RemoteAnimationTarget[] targets, View launcherView, PointF velocityPxPerS,
RectF closingWindowStartRectF, float startWindowCornerRadius) {
FloatingIconView floatingIconView = null;
FloatingWidgetView floatingWidget = null;
RectF targetRect = new RectF();
...... 省略
boolean useTaskbarHotseatParams = mDeviceProfile.isTaskbarPresent && isInHotseat;
//创建RectFSpringAnim动画实例
RectFSpringAnim anim = new RectFSpringAnim(useTaskbarHotseatParams
? ne

最低0.47元/天 解锁文章
3974

被折叠的 条评论
为什么被折叠?



