Merge "Scale recents on drag of tasks during dismiss." into main
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewDismissTouchController.kt b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewDismissTouchController.kt
index 98737a5..7a3cdb7 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewDismissTouchController.kt
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewDismissTouchController.kt
@@ -19,6 +19,7 @@
import android.view.MotionEvent
import androidx.dynamicanimation.animation.SpringAnimation
import com.android.app.animation.Interpolators.DECELERATE
+import com.android.app.animation.Interpolators.LINEAR
import com.android.launcher3.AbstractFloatingView
import com.android.launcher3.R
import com.android.launcher3.Utilities.EDGE_NAV_BAR
@@ -29,6 +30,7 @@
import com.android.launcher3.util.MSDLPlayerWrapper
import com.android.launcher3.util.TouchController
import com.android.quickstep.views.RecentsView
+import com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY
import com.android.quickstep.views.RecentsViewContainer
import com.android.quickstep.views.TaskView
import com.google.android.msdl.data.model.MSDLToken
@@ -57,6 +59,7 @@
private var verticalFactor: Int = 0
private var hasDismissThresholdHapticRun = false
private var initialDisplacement: Float = 0f
+ private var recentsScaleAnimation: SpringAnimation? = null
private fun canInterceptTouch(ev: MotionEvent): Boolean =
when {
@@ -98,6 +101,7 @@
private fun onActionDown(ev: MotionEvent): Boolean {
springAnimation?.cancel()
+ recentsScaleAnimation?.cancel()
if (!canInterceptTouch(ev)) {
return false
}
@@ -162,6 +166,8 @@
}
recentsView.redrawLiveTile()
}
+ val dismissFraction = displacement / (dismissLength * verticalFactor).toFloat()
+ RECENTS_SCALE_PROPERTY.setValue(recentsView, getRecentsScale(dismissFraction))
playDismissThresholdHaptic(displacement)
return true
}
@@ -216,6 +222,10 @@
if (isDismissing) (dismissLength * verticalFactor).toFloat() else 0f
)
}
+ recentsScaleAnimation =
+ recentsView.animateRecentsScale(RECENTS_SCALE_DEFAULT).addEndListener { _, _, _, _ ->
+ recentsScaleAnimation = null
+ }
}
// Returns if the current task being dragged is towards "positive" (e.g. dismissal).
@@ -230,8 +240,54 @@
springAnimation = null
}
+ private fun getRecentsScale(dismissFraction: Float): Float {
+ return when {
+ // Do not scale recents when dragging below origin.
+ dismissFraction <= 0 -> {
+ RECENTS_SCALE_DEFAULT
+ }
+ // Initially scale recents as the drag begins, up to the first threshold.
+ dismissFraction < RECENTS_SCALE_FIRST_THRESHOLD_FRACTION -> {
+ mapToRange(
+ dismissFraction,
+ 0f,
+ RECENTS_SCALE_FIRST_THRESHOLD_FRACTION,
+ RECENTS_SCALE_DEFAULT,
+ RECENTS_SCALE_ON_DISMISS_CANCEL,
+ LINEAR,
+ )
+ }
+ // Keep scale consistent until dragging to the dismiss threshold.
+ dismissFraction < RECENTS_SCALE_DISMISS_THRESHOLD_FRACTION -> {
+ RECENTS_SCALE_ON_DISMISS_CANCEL
+ }
+ // Scale beyond the dismiss threshold again, to indicate dismiss will occur on release.
+ dismissFraction < RECENTS_SCALE_SECOND_THRESHOLD_FRACTION -> {
+ mapToRange(
+ dismissFraction,
+ RECENTS_SCALE_DISMISS_THRESHOLD_FRACTION,
+ RECENTS_SCALE_SECOND_THRESHOLD_FRACTION,
+ RECENTS_SCALE_ON_DISMISS_CANCEL,
+ RECENTS_SCALE_ON_DISMISS_SUCCESS,
+ LINEAR,
+ )
+ }
+ // Keep scale beyond the dismiss threshold scaling consistent.
+ else -> {
+ RECENTS_SCALE_ON_DISMISS_SUCCESS
+ }
+ }
+ }
+
companion object {
private const val DISMISS_THRESHOLD_FRACTION = 0.5f
private const val DISMISS_THRESHOLD_HAPTIC_RANGE = 10f
+
+ private const val RECENTS_SCALE_ON_DISMISS_CANCEL = 0.9875f
+ private const val RECENTS_SCALE_ON_DISMISS_SUCCESS = 0.975f
+ private const val RECENTS_SCALE_DEFAULT = 1f
+ private const val RECENTS_SCALE_FIRST_THRESHOLD_FRACTION = 0.2f
+ private const val RECENTS_SCALE_DISMISS_THRESHOLD_FRACTION = 0.5f
+ private const val RECENTS_SCALE_SECOND_THRESHOLD_FRACTION = 0.575f
}
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 5bfcf43..0218a58 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -6947,6 +6947,13 @@
isDismissing, detector, dismissLength, onEndRunnable);
}
+ /**
+ * Animates RecentsView's scale to the provided value, using spring animations.
+ */
+ public SpringAnimation animateRecentsScale(float scale) {
+ return mUtils.animateRecentsScale(scale);
+ }
+
public interface TaskLaunchListener {
void onTaskLaunched();
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
index d3549fb..b38f7d1 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
+++ b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
@@ -35,6 +35,7 @@
import com.android.quickstep.util.GroupTask
import com.android.quickstep.util.TaskGridNavHelper
import com.android.quickstep.util.isExternalDisplay
+import com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY
import com.android.quickstep.views.RecentsView.RUNNING_TASK_ATTACH_ALPHA
import com.android.systemui.shared.recents.model.ThumbnailData
import com.google.android.msdl.data.model.MSDLToken
@@ -362,7 +363,6 @@
addNeighboringSpringAnimationsForDismissCancel(
draggedTaskView,
draggedTaskViewSpringAnimation,
- recentsView.pageCount,
)
}
return draggedTaskViewSpringAnimation
@@ -371,7 +371,6 @@
private fun addNeighboringSpringAnimationsForDismissCancel(
draggedTaskView: TaskView,
draggedTaskViewSpringAnimation: SpringAnimation,
- taskCount: Int,
) {
// Empty spring animation exists for conditional start, and to drive neighboring springs.
val neighborsToSettle =
@@ -532,10 +531,39 @@
)
}
+ /** Animates RecentsView's scale to the provided value, using spring animations. */
+ fun animateRecentsScale(scale: Float): SpringAnimation {
+ val resourceProvider = DynamicResource.provider(recentsView.mContainer)
+ val dampingRatio = resourceProvider.getFloat(R.dimen.swipe_up_rect_scale_damping_ratio)
+ val stiffness = resourceProvider.getFloat(R.dimen.swipe_up_rect_scale_stiffness)
+
+ // Spring which sets the Recents scale on update. This is needed, as the SpringAnimation
+ // struggles to animate small values like changing recents scale from 0.9 to 1. So
+ // we animate over a larger range (e.g. 900 to 1000) and convert back to the required value.
+ // (This is instead of converting RECENTS_SCALE_PROPERTY to a FloatPropertyCompat and
+ // animating it directly via springs.)
+ val initialRecentsScaleSpringValue =
+ RECENTS_SCALE_SPRING_MULTIPLIER * RECENTS_SCALE_PROPERTY.get(recentsView)
+ return SpringAnimation(FloatValueHolder(initialRecentsScaleSpringValue))
+ .setSpring(
+ SpringForce(initialRecentsScaleSpringValue)
+ .setDampingRatio(dampingRatio)
+ .setStiffness(stiffness)
+ )
+ .addUpdateListener { _, value, _ ->
+ RECENTS_SCALE_PROPERTY.setValue(
+ recentsView,
+ value / RECENTS_SCALE_SPRING_MULTIPLIER,
+ )
+ }
+ .apply { animateToFinalPosition(RECENTS_SCALE_SPRING_MULTIPLIER * scale) }
+ }
+
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
+ private const val ADDITIONAL_DISMISS_DAMPING_RATIO = 0.15f
+ private const val RECENTS_SCALE_SPRING_MULTIPLIER = 1000f
}
}