diff --git a/quickstep/src/com/android/quickstep/util/TaskGridNavHelper.java b/quickstep/src/com/android/quickstep/util/TaskGridNavHelper.java
index da266220ca..35e90f22b5 100644
--- a/quickstep/src/com/android/quickstep/util/TaskGridNavHelper.java
+++ b/quickstep/src/com/android/quickstep/util/TaskGridNavHelper.java
@@ -137,4 +137,12 @@ public class TaskGridNavHelper {
return currentPageTaskViewId;
}
}
+
+ /**
+ * Returns the column of a task's id in the grid.
+ */
+ public int getColumn(int taskViewId) {
+ return mTopRowIds.contains(taskViewId) ? mTopRowIds.indexOf(taskViewId)
+ : mBottomRowIds.indexOf(taskViewId);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
index d37a3f9d31..c7fc448690 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
+++ b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
@@ -392,47 +392,72 @@ class RecentsViewUtils(private val recentsView: RecentsView<*, *>) {
// Add tasks before dragged index, fanning out from the dragged task.
// The order they are added matters, as each spring drives the next.
var previousNeighbor = neighborsToSettle
- getTasksAdjacentToDraggedTask(draggedTaskView, towardsStart = true).forEach {
- previousNeighbor = createNeighboringTaskViewSpringAnimation(it, previousNeighbor)
+ getTasksOffsetPairAdjacentToDraggedTask(draggedTaskView, towardsStart = true).forEach {
+ (taskView, offset) ->
+ previousNeighbor =
+ createNeighboringTaskViewSpringAnimation(
+ taskView,
+ offset * ADDITIONAL_DISMISS_DAMPING_RATIO,
+ previousNeighbor,
+ )
}
// Add tasks after dragged index, fanning out from the dragged task.
// The order they are added matters, as each spring drives the next.
previousNeighbor = neighborsToSettle
- getTasksAdjacentToDraggedTask(draggedTaskView, towardsStart = false).forEach {
- previousNeighbor = createNeighboringTaskViewSpringAnimation(it, previousNeighbor)
+ getTasksOffsetPairAdjacentToDraggedTask(draggedTaskView, towardsStart = false).forEach {
+ (taskView, offset) ->
+ previousNeighbor =
+ createNeighboringTaskViewSpringAnimation(
+ taskView,
+ offset * ADDITIONAL_DISMISS_DAMPING_RATIO,
+ previousNeighbor,
+ )
}
}
- /** Gets adjacent tasks either before or after the dragged task in visual order. */
- private fun getTasksAdjacentToDraggedTask(
+ /**
+ * Gets pairs of (TaskView, offset) adjacent the dragged task in visual order.
+ *
+ *
Gets tasks either before or after the dragged task along with their offset from it. The
+ * offset is the distance between indices for carousels, or distance between columns for grids.
+ */
+ private fun getTasksOffsetPairAdjacentToDraggedTask(
draggedTaskView: TaskView,
towardsStart: Boolean,
- ): Sequence {
+ ): Sequence> {
if (recentsView.showAsGrid()) {
- return gridTaskViewInTabOrderSequence(draggedTaskView, towardsStart)
+ return gridTaskOffsetPairInTabOrderSequence(draggedTaskView, towardsStart)
} else {
val taskViewList = taskViews.toList()
val draggedTaskViewIndex = taskViewList.indexOf(draggedTaskView)
return if (towardsStart) {
- taskViewList.take(draggedTaskViewIndex).reversed().asSequence()
+ taskViewList
+ .take(draggedTaskViewIndex)
+ .reversed()
+ .mapIndexed { index, taskView -> Pair(taskView, index + 1) }
+ .asSequence()
} else {
- taskViewList.takeLast(taskViewList.size - draggedTaskViewIndex - 1).asSequence()
+ taskViewList
+ .takeLast(taskViewList.size - draggedTaskViewIndex - 1)
+ .mapIndexed { index, taskView -> Pair(taskView, index + 1) }
+ .asSequence()
}
}
}
/**
- * Returns a sequence of TaskViews in the grid, ordered according to tab navigation, starting
- * from the dragged TaskView, in the direction of the provided delta.
+ * Returns a sequence of pairs of (TaskViews, offsets) in the grid, ordered according to tab
+ * navigation, starting from the dragged TaskView, towards the start or end of the grid.
*
* A positive delta moves forward in the tab order towards the end of the grid, while a
- * negative value moves backward towards the beginning.
+ * negative value moves backward towards the beginning. The offset is the distance between
+ * columns the tasks are in.
*/
- private fun gridTaskViewInTabOrderSequence(
+ private fun gridTaskOffsetPairInTabOrderSequence(
draggedTaskView: TaskView,
towardsStart: Boolean,
- ): Sequence = sequence {
+ ): Sequence> = sequence {
val taskGridNavHelper =
TaskGridNavHelper(
recentsView.topRowIdArray,
@@ -440,6 +465,7 @@ class RecentsViewUtils(private val recentsView: RecentsView<*, *>) {
getLargeTaskViewIds(),
/* hasAddDesktopButton= */ false,
)
+ val draggedTaskViewColumn = taskGridNavHelper.getColumn(draggedTaskView.taskViewId)
var nextTaskView: TaskView? = draggedTaskView
var previousTaskView: TaskView? = null
while (nextTaskView != previousTaskView && nextTaskView != null) {
@@ -454,7 +480,11 @@ class RecentsViewUtils(private val recentsView: RecentsView<*, *>) {
)
)
if (nextTaskView != null && nextTaskView != previousTaskView) {
- yield(nextTaskView)
+ val columnOffset =
+ abs(
+ taskGridNavHelper.getColumn(nextTaskView.taskViewId) - draggedTaskViewColumn
+ )
+ yield(Pair(nextTaskView, columnOffset))
}
}
}
@@ -462,6 +492,7 @@ class RecentsViewUtils(private val recentsView: RecentsView<*, *>) {
/** Creates a neighboring task view spring, driven by the spring of its neighbor. */
private fun createNeighboringTaskViewSpringAnimation(
taskView: TaskView,
+ dampingOffsetRatio: Float,
previousNeighborSpringAnimation: SpringAnimation,
): SpringAnimation {
val neighboringTaskViewSpringAnimation =
@@ -471,7 +502,7 @@ class RecentsViewUtils(private val recentsView: RecentsView<*, *>) {
taskView.secondaryDismissTranslationProperty
),
)
- .setSpring(createExpressiveDismissSpringForce())
+ .setSpring(createExpressiveDismissSpringForce(dampingOffsetRatio))
// Update live tile on spring animation.
if (taskView.isRunningTask && recentsView.enableDrawingLiveTile) {
neighboringTaskViewSpringAnimation.addUpdateListener { _, _, _ ->
@@ -489,11 +520,12 @@ class RecentsViewUtils(private val recentsView: RecentsView<*, *>) {
return neighboringTaskViewSpringAnimation
}
- private fun createExpressiveDismissSpringForce(): SpringForce {
+ private fun createExpressiveDismissSpringForce(dampingRatioOffset: Float = 0f): SpringForce {
val resourceProvider = DynamicResource.provider(recentsView.mContainer)
return SpringForce()
.setDampingRatio(
- resourceProvider.getFloat(R.dimen.expressive_dismiss_task_trans_y_damping_ratio)
+ resourceProvider.getFloat(R.dimen.expressive_dismiss_task_trans_y_damping_ratio) +
+ dampingRatioOffset
)
.setStiffness(
resourceProvider.getFloat(R.dimen.expressive_dismiss_task_trans_y_stiffness)
@@ -502,5 +534,8 @@ class RecentsViewUtils(private val recentsView: RecentsView<*, *>) {
companion object {
val TEMP_RECT = Rect()
+
+ // The additional damping to apply to tasks further from the dismissed task.
+ const val ADDITIONAL_DISMISS_DAMPING_RATIO = 0.15f
}
}