diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index bd85d2c46c..9b34a73cf8 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -593,4 +593,8 @@
50
33
+ 40dp
+ - 0.8
+ - 380
+
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index e4f8f64a23..c152f1af72 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -5045,7 +5045,8 @@ public abstract class RecentsView<
*
* @param offsetProgress From 0 to 1 where 0 means no offset and 1 means offset offscreen.
*/
- private float getHorizontalOffsetSize(int childIndex, int midpointIndex, float offsetProgress) {
+ protected float getHorizontalOffsetSize(int childIndex, int midpointIndex,
+ float offsetProgress) {
if (offsetProgress == 0) {
// Don't bother calculating everything below if we won't offset anyway.
return 0;
diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
index 7a91e5bd3e..b6ea8aa2ae 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
+++ b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
@@ -29,11 +29,16 @@ import android.view.View.LAYOUT_DIRECTION_LTR
import android.view.View.LAYOUT_DIRECTION_RTL
import androidx.core.view.children
import androidx.core.view.isInvisible
+import androidx.dynamicanimation.animation.FloatPropertyCompat
+import androidx.dynamicanimation.animation.SpringAnimation
+import androidx.dynamicanimation.animation.SpringForce
import com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU
import com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType
import com.android.launcher3.Flags.enableDesktopExplodedView
import com.android.launcher3.Flags.enableLargeDesktopWindowingTile
import com.android.launcher3.Flags.enableOverviewOnConnectedDisplays
+import com.android.launcher3.PagedView.INVALID_PAGE
+import com.android.launcher3.R
import com.android.launcher3.Utilities.getPivotsForScalingRectToRect
import com.android.launcher3.statehandlers.DesktopVisibilityController
import com.android.launcher3.statehandlers.DesktopVisibilityController.Companion.INACTIVE_DESK_ID
@@ -256,6 +261,44 @@ class RecentsViewUtils(private val recentsView: RecentsView<*, *>) : DesktopVisi
recentsView.addDeskButton?.isInvisible = !canCreateDesks
}
+ private fun animateDesktopTaskViewSpringIn(desktopTaskView: DesktopTaskView) {
+ val taskDismissFloatProperty =
+ FloatPropertyCompat.createFloatPropertyCompat(
+ desktopTaskView.primaryDismissTranslationProperty
+ )
+
+ with(recentsView) {
+ // Calculate initial translation to bring it offscreen.
+ val desktopTaskViewIndex = indexOfChild(desktopTaskView)
+ val midpointIndex =
+ if (getTaskViewAt(desktopTaskViewIndex + 1) != null) desktopTaskViewIndex + 1
+ else INVALID_PAGE
+ var offscreenTranslationX =
+ getHorizontalOffsetSize(desktopTaskViewIndex, midpointIndex, 1f)
+
+ // Add 40dp to the offscreen translation.
+ val additionalOffsetPx =
+ context.resources.getDimensionPixelSize(
+ R.dimen.newly_created_desktop_offscreen_position
+ )
+ offscreenTranslationX += if (isRtl) additionalOffsetPx else -additionalOffsetPx
+ desktopTaskView.primaryDismissTranslationProperty.set(
+ desktopTaskView,
+ offscreenTranslationX,
+ )
+ desktopTaskView.isInvisible = false
+
+ val dampingRatio =
+ context.resources.getFloat(R.dimen.newly_created_desktop_spring_damping_ratio)
+ val stiffness =
+ context.resources.getFloat(R.dimen.newly_created_desktop_spring_stiffness)
+
+ SpringAnimation(desktopTaskView, taskDismissFloatProperty)
+ .setSpring(SpringForce(0f).setDampingRatio(dampingRatio).setStiffness(stiffness))
+ .start()
+ }
+ }
+
override fun onDeskAdded(displayId: Int, deskId: Int) {
with(recentsView) {
// Ignore desk changes that don't belong to this display.
@@ -278,12 +321,14 @@ class RecentsViewUtils(private val recentsView: RecentsView<*, *>) : DesktopVisi
pagedViewOrientedState,
taskOverlayFactory,
)
+ desktopTaskView.isInvisible = true
val insertionIndex = 1 + indexOfChild(addDeskButton!!)
addView(desktopTaskView, insertionIndex)
updateTaskSize()
updateChildTaskOrientations()
updateScrollSynchronously()
+ animateDesktopTaskViewSpringIn(desktopTaskView)
// Set Current Page based on the stored TaskView.
currentTaskView?.let { setCurrentPage(indexOfChild(it)) }