Run task reflow after dismiss earlier and increase spring constants.
This allows the user to dismiss multiple tasks in a row more quickly. Fix: 409485085 Test: Manual. Fling to dismiss tasks as quickly as possible. Flag: com.android.launcher3.enable_expressive_dismiss_task_motion Change-Id: I9a0d05c1a47b5bc0ef72cde055379e4df50b48b4
This commit is contained in:
-1
@@ -252,7 +252,6 @@ CONTAINER : RecentsViewContainer {
|
||||
taskBeingDragged,
|
||||
velocity,
|
||||
isDismissing,
|
||||
dismissLength,
|
||||
dismissThreshold,
|
||||
finalPosition,
|
||||
/* shouldRemoveTaskView= */ isDismissing,
|
||||
|
||||
+1
-2
@@ -246,8 +246,7 @@ public class TaskViewTouchControllerDeprecated<
|
||||
pa = new PendingAnimation(maxDuration);
|
||||
mRecentsView.createTaskDismissAnimation(pa, mTaskBeingDragged,
|
||||
true /* animateTaskView */, true /* removeTask */, maxDuration,
|
||||
false /* dismissingForSplitSelection*/, false /* isExpressiveDismiss */,
|
||||
null /* gridEndData */);
|
||||
false /* dismissingForSplitSelection*/, null /* gridEndData */);
|
||||
|
||||
mEndDisplacement = -secondaryTaskDimension;
|
||||
} else {
|
||||
|
||||
@@ -143,7 +143,7 @@ public class FallbackRecentsView<CONTAINER_TYPE extends Context & RecentsViewCon
|
||||
PendingAnimation pendingAnimation = new PendingAnimation(TASK_DISMISS_DURATION);
|
||||
createTaskDismissAnimation(pendingAnimation, homeTaskView, true, false,
|
||||
TASK_DISMISS_DURATION, false /* dismissingForSplitSelection*/,
|
||||
false /* isExpressiveDismiss */, null /* gridEndData */);
|
||||
null /* gridEndData */);
|
||||
pendingAnimation.addEndListener(e -> setCurrentTask(-1));
|
||||
AnimatorPlaybackController controller = pendingAnimation.createPlaybackController();
|
||||
controller.dispatchOnStart();
|
||||
|
||||
@@ -36,8 +36,6 @@ import com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY
|
||||
import com.android.quickstep.views.TaskView.Companion.GRID_END_TRANSLATION_X
|
||||
import com.android.systemui.shared.system.InteractionJankMonitorWrapper
|
||||
import com.google.android.msdl.data.model.MSDLToken
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
@@ -67,7 +65,6 @@ class RecentsDismissUtils(private val recentsView: RecentsView<*, *>) {
|
||||
draggedTaskView,
|
||||
velocity = 0f,
|
||||
isDismissing = true,
|
||||
dismissLength = 0,
|
||||
dismissThreshold = 0,
|
||||
finalPosition = 0f,
|
||||
shouldRemoveTaskView,
|
||||
@@ -91,7 +88,6 @@ class RecentsDismissUtils(private val recentsView: RecentsView<*, *>) {
|
||||
draggedTaskView,
|
||||
velocity,
|
||||
isDismissing = true,
|
||||
dismissLength,
|
||||
dismissThreshold,
|
||||
finalPosition,
|
||||
shouldRemoveTaskView,
|
||||
@@ -111,14 +107,18 @@ class RecentsDismissUtils(private val recentsView: RecentsView<*, *>) {
|
||||
draggedTaskView: TaskView?,
|
||||
velocity: Float,
|
||||
isDismissing: Boolean,
|
||||
dismissLength: Int,
|
||||
dismissThreshold: Int,
|
||||
finalPosition: Float,
|
||||
shouldRemoveTaskView: Boolean,
|
||||
isSplitSelection: Boolean,
|
||||
onEndRunnable: () -> Unit = {},
|
||||
): SpringAnimation? {
|
||||
val toRunOnEnd = {
|
||||
var toRunOnEndStarted = false
|
||||
val toRunOnEnd = toRunOnEnd@{
|
||||
// Enforce idempotence.
|
||||
if (toRunOnEndStarted) return@toRunOnEnd
|
||||
toRunOnEndStarted = true
|
||||
|
||||
if (isDismissing) {
|
||||
if (!recentsView.showAsGrid() || enableGridOnlyOverview()) {
|
||||
runTaskGridReflowSpringAnimation(
|
||||
@@ -150,8 +150,9 @@ class RecentsDismissUtils(private val recentsView: RecentsView<*, *>) {
|
||||
FloatPropertyCompat.createFloatPropertyCompat(
|
||||
draggedTaskView.secondaryDismissTranslationProperty
|
||||
)
|
||||
val minVelocity =
|
||||
recentsView.pagedOrientationHandler.getSecondaryDimension(draggedTaskView).toFloat()
|
||||
val dismissedTaskSecondaryDimension =
|
||||
recentsView.pagedOrientationHandler.getSecondaryDimension(draggedTaskView)
|
||||
val minVelocity = dismissedTaskSecondaryDimension.toFloat()
|
||||
val startVelocity = abs(velocity).coerceAtLeast(minVelocity) * velocity.sign
|
||||
var previousDisplacement = taskDismissFloatProperty.getValue(draggedTaskView)
|
||||
// Animate dragged task towards dismissal or rest state.
|
||||
@@ -159,7 +160,7 @@ class RecentsDismissUtils(private val recentsView: RecentsView<*, *>) {
|
||||
SpringAnimation(draggedTaskView, taskDismissFloatProperty)
|
||||
.setSpring(createExpressiveDismissSpringForce())
|
||||
.setStartVelocity(startVelocity)
|
||||
.addUpdateListener { animation, currentDisplacement, _ ->
|
||||
.addUpdateListener { _, currentDisplacement, _ ->
|
||||
// Play haptic as task crosses dismiss threshold from above or below.
|
||||
val previousBeyondThreshold = abs(previousDisplacement) >= abs(dismissThreshold)
|
||||
val currentBeyondThreshold = abs(currentDisplacement) >= abs(dismissThreshold)
|
||||
@@ -176,8 +177,13 @@ class RecentsDismissUtils(private val recentsView: RecentsView<*, *>) {
|
||||
}
|
||||
recentsView.redrawLiveTile()
|
||||
}
|
||||
if (isDismissing && abs(currentDisplacement) >= abs(dismissLength)) {
|
||||
animation.cancel()
|
||||
// If the dismissing task has moved enough to fit another task in its place,
|
||||
// start animating any other tasks that will fill the gap it left behind.
|
||||
if (
|
||||
isDismissing &&
|
||||
abs(currentDisplacement) >= abs(dismissedTaskSecondaryDimension)
|
||||
) {
|
||||
toRunOnEnd()
|
||||
}
|
||||
}
|
||||
.addEndListener { _, _, _, _ -> toRunOnEnd() }
|
||||
@@ -1168,22 +1174,22 @@ class RecentsDismissUtils(private val recentsView: RecentsView<*, *>) {
|
||||
|
||||
/** Tracks multiple springs so end runnable only runs once the last spring has ended. */
|
||||
private class SpringEndManager(val endRunnable: () -> Unit) {
|
||||
val runningSpringCount = AtomicInteger(0)
|
||||
var runningSpringCount = 0
|
||||
|
||||
fun addSpring(spring: SpringAnimation, endValue: Float) {
|
||||
runningSpringCount.incrementAndGet()
|
||||
val canSpringEnd = AtomicBoolean(false)
|
||||
runningSpringCount++
|
||||
var canSpringEnd = false
|
||||
spring.addUpdateListener { _, value, _ ->
|
||||
// Do not allow end listener to fire until we have reached the end value.
|
||||
if (abs(value - endValue) < spring.minimumVisibleChange && !canSpringEnd.get()) {
|
||||
canSpringEnd.set(true)
|
||||
if (!canSpringEnd && abs(value - endValue) < spring.minimumVisibleChange) {
|
||||
canSpringEnd = true
|
||||
}
|
||||
}
|
||||
spring.addEndListener { _, _, _, _ ->
|
||||
if (!canSpringEnd.get()) {
|
||||
if (!canSpringEnd) {
|
||||
return@addEndListener
|
||||
}
|
||||
if (runningSpringCount.decrementAndGet() == 0) {
|
||||
if (--runningSpringCount == 0) {
|
||||
endRunnable()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3706,15 +3706,13 @@ public abstract class RecentsView<
|
||||
* @param duration duration of the animation
|
||||
* @param dismissingForSplitSelection task dismiss animation is used for entering split
|
||||
* selection state from app icon
|
||||
* @param isExpressiveDismiss runs expressive animations controlled via
|
||||
* {@link RecentsDismissUtils}
|
||||
* @param gridEndData used to compute any gap left between the end of the
|
||||
* grid and the clear all button.
|
||||
*/
|
||||
public void createTaskDismissAnimation(PendingAnimation anim,
|
||||
@Nullable TaskView dismissedTaskView,
|
||||
boolean animateTaskView, boolean shouldRemoveTask, long duration,
|
||||
boolean dismissingForSplitSelection, boolean isExpressiveDismiss,
|
||||
boolean dismissingForSplitSelection,
|
||||
@Nullable RecentsDismissUtils.GridEndData gridEndData) {
|
||||
if (mPendingAnimation != null) {
|
||||
mPendingAnimation.createPlaybackController().dispatchOnCancel().dispatchOnEnd();
|
||||
@@ -3796,9 +3794,9 @@ public abstract class RecentsView<
|
||||
boolean isClearAllHidden = isClearAllHidden();
|
||||
|
||||
if (gridEndData == null) {
|
||||
gridEndData = mDismissUtils.getGridEndData(dismissedTaskView, isExpressiveDismiss,
|
||||
isFocusedTaskDismissed, nextFocusedTaskView, isStagingFocusedTask,
|
||||
nextFocusedTaskFromTop, nextFocusedTaskWidth);
|
||||
gridEndData = mDismissUtils.getGridEndData(dismissedTaskView,
|
||||
false /* isExpressiveDismiss */, isFocusedTaskDismissed, nextFocusedTaskView,
|
||||
isStagingFocusedTask, nextFocusedTaskFromTop, nextFocusedTaskWidth);
|
||||
}
|
||||
float longGridRowWidthDiff = gridEndData.getGridEndOffset();
|
||||
boolean snapToLastTask = gridEndData.getSnapToLastTask();
|
||||
@@ -3812,7 +3810,7 @@ public abstract class RecentsView<
|
||||
// After dismissal, animate translation of the remaining tasks to fill any gap left
|
||||
// between the end of the grid and the clear all button. Only animate if the clear
|
||||
// all button is visible or would become visible after dismissal.
|
||||
if (!isExpressiveDismiss && longGridRowWidthDiff != 0) {
|
||||
if (longGridRowWidthDiff != 0) {
|
||||
// If we need to animate the grid to compensate the clear all gap, we split the
|
||||
// second half of the dismiss pending animation (in which the non-dismissed tasks
|
||||
// slide into place) in half again, making the first quarter the existing
|
||||
@@ -3873,9 +3871,7 @@ public abstract class RecentsView<
|
||||
slidingTranslation += mIsRtl ? newClearAllShortTotalWidthTranslation
|
||||
: -newClearAllShortTotalWidthTranslation;
|
||||
}
|
||||
if (!isExpressiveDismiss) {
|
||||
mTaskViewsDismissPrimaryTranslations.clear();
|
||||
}
|
||||
mTaskViewsDismissPrimaryTranslations.clear();
|
||||
int lastTaskViewIndex = indexOfChild(mUtils.getLastTaskView());
|
||||
for (int i = 0; i < count; i++) {
|
||||
View child = getChildAt(i);
|
||||
@@ -3890,16 +3886,14 @@ public abstract class RecentsView<
|
||||
lastTaskViewIndex);
|
||||
int scrollDiff = newScroll[i] - oldScroll[i] + offset;
|
||||
if (scrollDiff != 0) {
|
||||
if (!isExpressiveDismiss) {
|
||||
translateTaskWhenDismissed(
|
||||
child,
|
||||
Math.abs(i - dismissedIndex),
|
||||
scrollDiff,
|
||||
anim,
|
||||
splitTimings);
|
||||
if (child instanceof TaskView taskView) {
|
||||
mTaskViewsDismissPrimaryTranslations.put(taskView, scrollDiffPerPage);
|
||||
}
|
||||
translateTaskWhenDismissed(
|
||||
child,
|
||||
Math.abs(i - dismissedIndex),
|
||||
scrollDiff,
|
||||
anim,
|
||||
splitTimings);
|
||||
if (child instanceof TaskView taskView) {
|
||||
mTaskViewsDismissPrimaryTranslations.put(taskView, scrollDiffPerPage);
|
||||
}
|
||||
needsCurveUpdates = true;
|
||||
}
|
||||
@@ -3985,22 +3979,19 @@ public abstract class RecentsView<
|
||||
: finalTranslation + (mIsRtl ? -mLastComputedTaskSize.right
|
||||
: mLastComputedTaskSize.right);
|
||||
}
|
||||
// Expressive dismiss will animate the translations of taskViews itself.
|
||||
if (!isExpressiveDismiss) {
|
||||
Animator dismissAnimator = ObjectAnimator.ofFloat(taskView,
|
||||
taskView.getPrimaryDismissTranslationProperty(),
|
||||
startTranslation, finalTranslation);
|
||||
dismissAnimator.setInterpolator(
|
||||
clampToProgress(dismissInterpolator, animationStartProgress,
|
||||
animationEndProgress));
|
||||
anim.add(dismissAnimator);
|
||||
mTaskViewsDismissPrimaryTranslations.put(taskView, (int) finalTranslation);
|
||||
}
|
||||
Animator dismissAnimator = ObjectAnimator.ofFloat(taskView,
|
||||
taskView.getPrimaryDismissTranslationProperty(),
|
||||
startTranslation, finalTranslation);
|
||||
dismissAnimator.setInterpolator(
|
||||
clampToProgress(dismissInterpolator, animationStartProgress,
|
||||
animationEndProgress));
|
||||
anim.add(dismissAnimator);
|
||||
mTaskViewsDismissPrimaryTranslations.put(taskView, (int) finalTranslation);
|
||||
distanceFromDismissedTask++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dismissingForSplitSelection && !isExpressiveDismiss) {
|
||||
if (dismissingForSplitSelection) {
|
||||
createInitialSplitSelectAnimation(anim);
|
||||
}
|
||||
|
||||
@@ -4551,22 +4542,11 @@ public abstract class RecentsView<
|
||||
PendingAnimation pa = new PendingAnimation(DISMISS_TASK_DURATION);
|
||||
createTaskDismissAnimation(pa, taskView, animateTaskView, removeTask,
|
||||
DISMISS_TASK_DURATION, false /* dismissingForSplitSelection*/,
|
||||
false /* isExpressiveDismiss */, null /* gridEndData */);
|
||||
null /* gridEndData */);
|
||||
runDismissAnimation(pa);
|
||||
}
|
||||
}
|
||||
|
||||
protected void expressiveDismissTaskView(TaskView taskView, Function0<Unit> onEndRunnable,
|
||||
int dismissDuration, boolean shouldRemoveTaskView,
|
||||
@Nullable RecentsDismissUtils.GridEndData gridEndData) {
|
||||
PendingAnimation pa = new PendingAnimation(dismissDuration);
|
||||
createTaskDismissAnimation(pa, taskView, false /* animateTaskView */, shouldRemoveTaskView,
|
||||
dismissDuration, false /* dismissingForSplitSelection*/,
|
||||
true /* isExpressiveDismiss */, gridEndData);
|
||||
pa.addEndListener((success) -> onEndRunnable.invoke());
|
||||
runDismissAnimation(pa);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void dismissAllTasks(View view) {
|
||||
runDismissAnimation(createAllTasksDismissAnimation(DISMISS_TASK_DURATION));
|
||||
@@ -5310,8 +5290,7 @@ public abstract class RecentsView<
|
||||
runExpressiveSplit(builder, mSplitHiddenTaskView);
|
||||
} else {
|
||||
createTaskDismissAnimation(builder, mSplitHiddenTaskView, true, false, duration,
|
||||
true /* dismissingForSplitSelection*/, false /* isExpressiveDismiss */,
|
||||
null /* gridEndData */);
|
||||
true /* dismissingForSplitSelection*/, null /* gridEndData */);
|
||||
}
|
||||
} else {
|
||||
// Splitting from Home
|
||||
@@ -5324,8 +5303,7 @@ public abstract class RecentsView<
|
||||
runExpressiveSplit(builder, /* taskView= */ null);
|
||||
} else {
|
||||
createTaskDismissAnimation(builder, null, true, false, duration,
|
||||
true /* dismissingForSplitSelection*/, false /* isExpressiveDismiss */,
|
||||
null /* gridEndData */);
|
||||
true /* dismissingForSplitSelection*/, null /* gridEndData */);
|
||||
}
|
||||
} else {
|
||||
createInitialSplitSelectAnimation(builder);
|
||||
@@ -7003,11 +6981,11 @@ public abstract class RecentsView<
|
||||
* spring in response to the perceived impact of the settling task.
|
||||
*/
|
||||
public SpringAnimation runTaskDismissSettlingSpringAnimation(TaskView draggedTaskView,
|
||||
float velocity, boolean isDismissing, int dismissLength, int dismissThreshold,
|
||||
float finalPosition, boolean shouldRemoveTaskView, boolean isSplitSelection,
|
||||
float velocity, boolean isDismissing, int dismissThreshold, float finalPosition,
|
||||
boolean shouldRemoveTaskView, boolean isSplitSelection,
|
||||
@NonNull Function0<Unit> onEndRunnable) {
|
||||
return mDismissUtils.createTaskDismissSettlingSpringAnimation(draggedTaskView, velocity,
|
||||
isDismissing, dismissLength, dismissThreshold, finalPosition, shouldRemoveTaskView,
|
||||
isDismissing, dismissThreshold, finalPosition, shouldRemoveTaskView,
|
||||
isSplitSelection, onEndRunnable);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
<item name="expressive_dismiss_task_trans_y_damping_ratio" type="dimen" format="float">0.6</item>
|
||||
<item name="expressive_dismiss_task_trans_y_stiffness" type="dimen" format="float">900</item>
|
||||
<item name="expressive_dismiss_task_trans_x_damping_ratio" type="dimen" format="float">0.8</item>
|
||||
<item name="expressive_dismiss_task_trans_x_stiffness" type="dimen" format="float">900</item>
|
||||
<item name="expressive_dismiss_task_trans_x_stiffness" type="dimen" format="float">3000</item>
|
||||
<item name="expressive_dismiss_effects_damping_ratio" type="dimen" format="float">1</item>
|
||||
<item name="expressive_dismiss_effects_stiffness" type="dimen" format="float">1600</item>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user