diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index 7a50d0bf63..be5ab55353 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -207,59 +207,10 @@ import java.util.function.Supplier; private Animator onStateChangeApplied(int changedFlags, long duration, boolean start) { AnimatorSet animatorSet = new AnimatorSet(); - if (hasAnyFlag(changedFlags, FLAG_RESUMED)) { - boolean isResumed = isResumed(); - ObjectAnimator anim = mIconAlignmentForResumedState - .animateToValue(isResumed && goingToUnstashedLauncherState() - ? 1 : 0) - .setDuration(duration); - - anim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mIsAnimatingToLauncherViaResume = false; - } - - @Override - public void onAnimationStart(Animator animation) { - mIsAnimatingToLauncherViaResume = isResumed; - - TaskbarStashController stashController = mControllers.taskbarStashController; - stashController.updateStateForFlag(FLAG_IN_APP, !isResumed); - stashController.applyState(duration); - } - }); - animatorSet.play(anim); - } - - if (hasAnyFlag(changedFlags, FLAG_RECENTS_ANIMATION_RUNNING)) { - boolean isRecentsAnimationRunning = isRecentsAnimationRunning(); - Animator animator = mIconAlignmentForGestureState - .animateToValue(isRecentsAnimationRunning && goingToUnstashedLauncherState() - ? 1 : 0); - if (isRecentsAnimationRunning) { - animator.setDuration(duration); - } - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mIsAnimatingToLauncherViaGesture = false; - } - - @Override - public void onAnimationStart(Animator animation) { - mIsAnimatingToLauncherViaGesture = isRecentsAnimationRunning(); - } - }); - animatorSet.play(animator); - } - - if (hasAnyFlag(changedFlags, FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING)) { - boolean goingToLauncher = hasAnyFlag(FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING); - animatorSet.play(mTaskbarBackgroundAlpha.animateToValue(goingToLauncher ? 0 : 1) - .setDuration(duration)); - } + // Add the state animation first to ensure FLAG_IN_STASHED_LAUNCHER_STATE is set and we can + // determine whether goingToUnstashedLauncherStateChanged. + boolean wasGoingToUnstashedLauncherState = goingToUnstashedLauncherState(); if (hasAnyFlag(changedFlags, FLAG_TRANSITION_STATE_RUNNING)) { boolean committed = !hasAnyFlag(FLAG_TRANSITION_STATE_RUNNING); playStateTransitionAnim(animatorSet, duration, committed); @@ -270,6 +221,76 @@ import java.util.function.Supplier; applyState(0 /* duration */); } } + boolean goingToUnstashedLauncherStateChanged = wasGoingToUnstashedLauncherState + != goingToUnstashedLauncherState(); + + boolean launcherStateChangedDuringAnimToResumeAlignment = + mIconAlignmentForResumedState.isAnimating() && goingToUnstashedLauncherStateChanged; + if (hasAnyFlag(changedFlags, FLAG_RESUMED) + || launcherStateChangedDuringAnimToResumeAlignment) { + boolean isResumed = isResumed(); + float toAlignmentForResumedState = isResumed && goingToUnstashedLauncherState() ? 1 : 0; + // If we're already animating to the value, just leave it be instead of restarting it. + if (!mIconAlignmentForResumedState.isAnimatingToValue(toAlignmentForResumedState)) { + ObjectAnimator resumeAlignAnim = mIconAlignmentForResumedState + .animateToValue(toAlignmentForResumedState) + .setDuration(duration); + + resumeAlignAnim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mIsAnimatingToLauncherViaResume = false; + } + + @Override + public void onAnimationStart(Animator animation) { + mIsAnimatingToLauncherViaResume = isResumed; + + TaskbarStashController stashController = + mControllers.taskbarStashController; + stashController.updateStateForFlag(FLAG_IN_APP, !isResumed); + stashController.applyState(duration); + } + }); + animatorSet.play(resumeAlignAnim); + } + } + + + boolean launcherStateChangedDuringAnimToGestureAlignment = + mIconAlignmentForGestureState.isAnimating() && goingToUnstashedLauncherStateChanged; + if (hasAnyFlag(changedFlags, FLAG_RECENTS_ANIMATION_RUNNING) + || launcherStateChangedDuringAnimToGestureAlignment) { + boolean isRecentsAnimationRunning = isRecentsAnimationRunning(); + float toAlignmentForGestureState = isRecentsAnimationRunning + && goingToUnstashedLauncherState() ? 1 : 0; + // If we're already animating to the value, just leave it be instead of restarting it. + if (!mIconAlignmentForGestureState.isAnimatingToValue(toAlignmentForGestureState)) { + Animator gestureAlignAnim = mIconAlignmentForGestureState + .animateToValue(toAlignmentForGestureState); + if (isRecentsAnimationRunning) { + gestureAlignAnim.setDuration(duration); + } + gestureAlignAnim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mIsAnimatingToLauncherViaGesture = false; + } + + @Override + public void onAnimationStart(Animator animation) { + mIsAnimatingToLauncherViaGesture = isRecentsAnimationRunning(); + } + }); + animatorSet.play(gestureAlignAnim); + } + } + + if (hasAnyFlag(changedFlags, FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING)) { + boolean goingToLauncher = hasAnyFlag(FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING); + animatorSet.play(mTaskbarBackgroundAlpha.animateToValue(goingToLauncher ? 0 : 1) + .setDuration(duration)); + } if (start) { animatorSet.start(); @@ -310,8 +331,11 @@ import java.util.function.Supplier; animatorSet.play(stashAnimator); } - animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment) - .setDuration(duration)); + // If we're already animating to the value, just leave it be instead of restarting it. + if (!mIconAlignmentForLauncherState.isAnimatingToValue(toAlignment)) { + animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment) + .setDuration(duration)); + } } private boolean isResumed() { diff --git a/quickstep/src/com/android/quickstep/AnimatedFloat.java b/quickstep/src/com/android/quickstep/AnimatedFloat.java index 95c871099b..6a7d066cd8 100644 --- a/quickstep/src/com/android/quickstep/AnimatedFloat.java +++ b/quickstep/src/com/android/quickstep/AnimatedFloat.java @@ -42,6 +42,8 @@ public class AnimatedFloat { private final Runnable mUpdateCallback; private ObjectAnimator mValueAnimator; + // Only non-null when an animation is playing to this value. + private Float mEndValue; public float value; @@ -67,10 +69,18 @@ public class AnimatedFloat { cancelAnimation(); mValueAnimator = ObjectAnimator.ofFloat(this, VALUE, start, end); mValueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + if (mValueAnimator == animator) { + mEndValue = end; + } + } + @Override public void onAnimationEnd(Animator animator) { if (mValueAnimator == animator) { mValueAnimator = null; + mEndValue = null; } } }); @@ -103,4 +113,15 @@ public class AnimatedFloat { public ObjectAnimator getCurrentAnimation() { return mValueAnimator; } + + public boolean isAnimating() { + return mValueAnimator != null; + } + + /** + * Returns whether we are currently animating, and the animation's end value matches the given. + */ + public boolean isAnimatingToValue(float endValue) { + return isAnimating() && mEndValue != null && mEndValue == endValue; + } }