diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index c45947205f..7c9a2b8f3c 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -39,6 +39,11 @@ 90dp 110dp + + 2.25dp + 1.75dp + 0.75dp + 16dp 70dp diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java index 70b3870a6c..c6ea953aff 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java @@ -28,6 +28,7 @@ import android.view.animation.Interpolator; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.LauncherAnimUtils; +import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; @@ -50,6 +51,10 @@ public abstract class TaskViewTouchController extends AnimatorListenerAdapter implements TouchController, SingleAxisSwipeDetector.Listener { + private static final float ANIMATION_PROGRESS_FRACTION_MIDPOINT = 0.5f; + private static final long MIN_TASK_DISMISS_ANIMATION_DURATION = 300; + private static final long MAX_TASK_DISMISS_ANIMATION_DURATION = 600; + protected final T mActivity; private final SingleAxisSwipeDetector mDetector; private final RecentsView mRecentsView; @@ -277,14 +282,32 @@ public abstract class TaskViewTouchController } else { mFlingBlockCheck.onEvent(); } - mCurrentAnimation.setPlayFraction(Utilities.boundToRange( - totalDisplacement * mProgressMultiplier, 0, 1)); + + // Once halfway through task dismissal interpolation, switch from reversible dragging-task + // animation to playing the remaining task translation animations + if (mCurrentAnimation.getProgressFraction() < ANIMATION_PROGRESS_FRACTION_MIDPOINT) { + // Halve the value as we are animating the drag across the full length for only the + // first half of the progress + mCurrentAnimation.setPlayFraction( + Utilities.boundToRange(totalDisplacement * mProgressMultiplier / 2, 0, 1)); + } else { + float dragVelocity = -mTaskBeingDragged.getResources().getDimension( + mRecentsView.showAsGrid() ? R.dimen.default_task_dismiss_drag_velocity_grid + : R.dimen.default_task_dismiss_drag_velocity); + onDragEnd(dragVelocity); + return true; + } return true; } @Override public void onDragEnd(float velocity) { + // Limit velocity, as very large scalar values make animations play too quickly + float maxTaskDismissDragVelocity = mTaskBeingDragged.getResources().getDimension( + R.dimen.max_task_dismiss_drag_velocity); + velocity = Utilities.boundToRange(velocity, -maxTaskDismissDragVelocity, + maxTaskDismissDragVelocity); boolean fling = mDetector.isFling(velocity); final boolean goingToEnd; boolean blockedFling = fling && mFlingBlockCheck.isBlocked(); @@ -305,6 +328,11 @@ public abstract class TaskViewTouchController if (blockedFling && !goingToEnd) { animationDuration *= LauncherAnimUtils.blockedFlingDurationFactor(velocity); } + // Due to very high or low velocity dismissals, animation durations can be inconsistently + // long or short. Bound the duration for animation of task translations for a more + // standardized feel. + animationDuration = Utilities.boundToRange(animationDuration, + MIN_TASK_DISMISS_ANIMATION_DURATION, MAX_TASK_DISMISS_ANIMATION_DURATION); mCurrentAnimation.setEndAction(this::clearState); mCurrentAnimation.startWithVelocity(mActivity, goingToEnd, diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 67f9063ca1..4cdae2768e 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -32,11 +32,12 @@ import static com.android.launcher3.Utilities.mapToRange; import static com.android.launcher3.Utilities.squaredHypot; import static com.android.launcher3.Utilities.squaredTouchSlop; import static com.android.launcher3.anim.Interpolators.ACCEL; +import static com.android.launcher3.anim.Interpolators.ACCEL_0_5; import static com.android.launcher3.anim.Interpolators.ACCEL_0_75; -import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.launcher3.anim.Interpolators.clampToProgress; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN; @@ -336,6 +337,11 @@ public abstract class RecentsView mSizeStrategy; protected RecentsAnimationController mRecentsAnimationController; @@ -358,10 +364,6 @@ public abstract class RecentsView mScrollListeners = new ArrayList<>(); private float mFullscreenScale; - private static final int DISMISS_TASK_DURATION = 300; - private static final int DISMISS_TASK_TRANSLATION_DURATION = 200; - private static final int ADDITIONAL_DISMISS_TASK_TRANSLATION_DURATION = 75; - private static final int ADDITION_TASK_DURATION = 200; // The threshold at which we update the SystemUI flags when animating from the task into the app public static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.85f; @@ -1886,21 +1888,18 @@ public abstract class RecentsView= dismissed index and in the - // same row as the dismissed index, or if the dismissed task was the focused task. Offset - // successive task dismissal durations for a staggered effect. - ArrayList gridTranslationAnimators = new ArrayList<>(); - boolean isFocusedTaskDismissed = - isTaskDismissal && dismissedTask.getTask().key.id == mFocusedTaskId; for (int i = 0; i < taskCount; i++) { TaskView taskView = getTaskViewAt(i); - if (isFocusedTaskDismissed || (i >= dismissedIndex && isSameGridRow(dismissedTask, - taskView))) { - Animator taskDismissAnimator = ObjectAnimator.ofFloat(taskView, - taskView.getPrimaryDismissTranslationProperty(), - mIsRtl ? -dismissedTaskWidth : dismissedTaskWidth, 0f); - int additionalTranslationDuration = - i >= dismissedIndex ? (ADDITIONAL_DISMISS_TASK_TRANSLATION_DURATION * ( - (i - dismissedIndex) / 2)) : 0; - taskDismissAnimator.setDuration( - DISMISS_TASK_TRANSLATION_DURATION + additionalTranslationDuration); - gridTranslationAnimators.add(taskDismissAnimator); - } taskView.setGridTranslationX(gridTranslations[i] - snappedTaskGridTranslationX); taskView.getPrimaryNonFullscreenTranslationProperty().set(taskView, snappedTaskFullscreenScrollAdjustment); taskView.getSecondaryNonFullscreenTranslationProperty().set(taskView, 0f); } - AnimatorSet gridTranslationAnimatorSet = new AnimatorSet(); - gridTranslationAnimatorSet.playTogether(gridTranslationAnimators); - gridTranslationAnimatorSet.start(); // Use the accumulated translation of the row containing the last task. float clearAllAccumulatedTranslation = topSet.contains(taskCount - 1) @@ -2210,7 +2184,7 @@ public abstract class RecentsView { @@ -2283,6 +2259,11 @@ public abstract class RecentsView= dismissed index and in the same row as the + // dismissed index, or if the dismissed task was the focused task. Offset + // successive task dismissal durations for a staggered effect. + if (isFocusedTaskDismissed || (i >= draggedIndex && isSameGridRow((TaskView) child, + taskView))) { + FloatProperty translationProperty = + ((TaskView) child).getPrimaryDismissTranslationProperty(); + float additionalDismissDuration = + ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * Math.abs( + i - draggedIndex); + anim.setFloat(child, translationProperty, + !mIsRtl ? -dismissedTaskWidth : dismissedTaskWidth, + clampToProgress(LINEAR, Utilities.boundToRange( + INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + + additionalDismissDuration, 0f, 1f), 1)); + } } } @@ -2364,6 +2361,10 @@ public abstract class RecentsView { + if (t == lowerBound && t == upperBound) { + return t == 0f ? 0 : 1; + } if (t < lowerBound) { return 0; }