From a429fdbbe6162d071026c97ccd30cdf7eec49037 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 1 May 2019 11:23:52 -0700 Subject: [PATCH] End window animation to home when handler invalidated We did this already for mCurrentShift, which is used for all animations except home animation. Now we do it for the home animation as well to ensure we are properly cleaned up for the next interaction. Test: Swipe up to home and double tap nav region before animation finishes. Before, this would return to the app you swiped up from but was in a broken state where subsequent swipes were ignored. Now we jump to the home screen and remain there. Bug: 130802487 Change-Id: I98a2e71a1791f5580451c94a35af98da193ff12f --- .../WindowTransformSwipeHandler.java | 28 +++++++++++++-- .../quickstep/util/RectFSpringAnim.java | 36 +++++++++++++------ .../launcher3/anim/FlingSpringAnim.java | 14 ++++++-- 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index 3797e87995..7076f58d94 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -220,6 +220,8 @@ public class WindowTransformSwipeHandler protected Runnable mGestureEndCallback; protected GestureEndTarget mGestureEndTarget; + // Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise + private RunningWindowAnim mRunningWindowAnim; private boolean mIsShelfPeeking; private DeviceProfile mDp; private int mTransitionDragLength; @@ -805,7 +807,7 @@ public class WindowTransformSwipeHandler @UiThread private InputConsumer createNewInputProxyHandler() { - mCurrentShift.finishAnimation(); + endRunningWindowAnim(); if (mLauncherTransitionController != null) { mLauncherTransitionController.getAnimationPlayer().end(); } @@ -817,6 +819,12 @@ public class WindowTransformSwipeHandler return OverviewInputConsumer.newInstance(mActivityControlHelper, null, true); } + private void endRunningWindowAnim() { + if (mRunningWindowAnim != null) { + mRunningWindowAnim.end(); + } + } + @UiThread private void handleNormalGestureEnd(float endVelocity, boolean isFling, PointF velocity, boolean isCancel) { @@ -984,6 +992,7 @@ public class WindowTransformSwipeHandler } }); windowAnim.start(velocityPxPerMs); + mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim); mLauncherTransitionController = null; } else { ValueAnimator windowAnim = mCurrentShift.animateToValue(start, end); @@ -1002,6 +1011,7 @@ public class WindowTransformSwipeHandler } }); windowAnim.start(); + mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim); } // Always play the entire launcher animation when going home, since it is separate from // the animation that has been controlled thus far. @@ -1111,7 +1121,7 @@ public class WindowTransformSwipeHandler false /* animate */, true /* freezeTaskList */); }); } - TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", false); + TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", true); doLogGesture(NEW_TASK); reset(); } @@ -1133,7 +1143,7 @@ public class WindowTransformSwipeHandler } private void invalidateHandler() { - mCurrentShift.finishAnimation(); + endRunningWindowAnim(); if (mGestureEndCallback != null) { mGestureEndCallback.run(); @@ -1281,4 +1291,16 @@ public class WindowTransformSwipeHandler return app.isNotInRecents || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME; } + + private interface RunningWindowAnim { + void end(); + + static RunningWindowAnim wrap(Animator animator) { + return animator::end; + } + + static RunningWindowAnim wrap(RectFSpringAnim rectFSpringAnim) { + return rectFSpringAnim::end; + } + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java index 2edeb3aec2..7159e7c721 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java @@ -23,6 +23,9 @@ import android.graphics.PointF; import android.graphics.RectF; import android.util.FloatProperty; +import androidx.dynamicanimation.animation.DynamicAnimation.OnAnimationEndListener; +import androidx.dynamicanimation.animation.FloatPropertyCompat; + import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.FlingSpringAnim; @@ -30,9 +33,6 @@ import com.android.launcher3.anim.FlingSpringAnim; import java.util.ArrayList; import java.util.List; -import androidx.dynamicanimation.animation.DynamicAnimation.OnAnimationEndListener; -import androidx.dynamicanimation.animation.FloatPropertyCompat; - /** * Applies spring forces to animate from a starting rect to a target rect, * while providing update callbacks to the caller. @@ -98,6 +98,10 @@ public class RectFSpringAnim { private float mCurrentCenterX; private float mCurrentCenterY; private float mCurrentScaleProgress; + private FlingSpringAnim mRectXAnim; + private FlingSpringAnim mRectYAnim; + private ValueAnimator mRectScaleAnim; + private boolean mAnimsStarted; private boolean mRectXAnimEnded; private boolean mRectYAnimEnded; private boolean mRectScaleAnimEnded; @@ -127,15 +131,15 @@ public class RectFSpringAnim { mRectYAnimEnded = true; maybeOnEnd(); }); - FlingSpringAnim rectXAnim = new FlingSpringAnim(this, RECT_CENTER_X, mCurrentCenterX, + mRectXAnim = new FlingSpringAnim(this, RECT_CENTER_X, mCurrentCenterX, mTargetRect.centerX(), velocityPxPerMs.x * 1000, onXEndListener); - FlingSpringAnim rectYAnim = new FlingSpringAnim(this, RECT_CENTER_Y, mCurrentCenterY, + mRectYAnim = new FlingSpringAnim(this, RECT_CENTER_Y, mCurrentCenterY, mTargetRect.centerY(), velocityPxPerMs.y * 1000, onYEndListener); - ValueAnimator rectScaleAnim = ObjectAnimator.ofPropertyValuesHolder(this, + mRectScaleAnim = ObjectAnimator.ofPropertyValuesHolder(this, PropertyValuesHolder.ofFloat(RECT_SCALE_PROGRESS, 1)) .setDuration(RECT_SCALE_DURATION); - rectScaleAnim.addListener(new AnimationSuccessListener() { + mRectScaleAnim.addListener(new AnimationSuccessListener() { @Override public void onAnimationSuccess(Animator animator) { mRectScaleAnimEnded = true; @@ -143,14 +147,23 @@ public class RectFSpringAnim { } }); - rectXAnim.start(); - rectYAnim.start(); - rectScaleAnim.start(); + mRectXAnim.start(); + mRectYAnim.start(); + mRectScaleAnim.start(); + mAnimsStarted = true; for (Animator.AnimatorListener animatorListener : mAnimatorListeners) { animatorListener.onAnimationStart(null); } } + public void end() { + if (mAnimsStarted) { + mRectXAnim.end(); + mRectYAnim.end(); + mRectScaleAnim.end(); + } + } + private void onUpdate() { if (!mOnUpdateListeners.isEmpty()) { float currentWidth = Utilities.mapRange(mCurrentScaleProgress, mStartRect.width(), @@ -166,7 +179,8 @@ public class RectFSpringAnim { } private void maybeOnEnd() { - if (mRectXAnimEnded && mRectYAnimEnded && mRectScaleAnimEnded) { + if (mAnimsStarted && mRectXAnimEnded && mRectYAnimEnded && mRectScaleAnimEnded) { + mAnimsStarted = false; for (Animator.AnimatorListener animatorListener : mAnimatorListeners) { animatorListener.onAnimationEnd(null); } diff --git a/src/com/android/launcher3/anim/FlingSpringAnim.java b/src/com/android/launcher3/anim/FlingSpringAnim.java index 3d21d82a25..45d49e8706 100644 --- a/src/com/android/launcher3/anim/FlingSpringAnim.java +++ b/src/com/android/launcher3/anim/FlingSpringAnim.java @@ -34,6 +34,7 @@ public class FlingSpringAnim { private static final float SPRING_DAMPING = SpringForce.DAMPING_RATIO_LOW_BOUNCY; private final FlingAnimation mFlingAnim; + private SpringAnimation mSpringAnim; public FlingSpringAnim(K object, FloatPropertyCompat property, float startPosition, float targetPosition, float startVelocity, OnAnimationEndListener onEndListener) { @@ -44,17 +45,24 @@ public class FlingSpringAnim { .setMinValue(Math.min(startPosition, targetPosition)) .setMaxValue(Math.max(startPosition, targetPosition)); mFlingAnim.addEndListener(((animation, canceled, value, velocity) -> { - SpringAnimation springAnim = new SpringAnimation(object, property) + mSpringAnim = new SpringAnimation(object, property) .setStartVelocity(velocity) .setSpring(new SpringForce(targetPosition) .setStiffness(SPRING_STIFFNESS) .setDampingRatio(SPRING_DAMPING)); - springAnim.addEndListener(onEndListener); - springAnim.start(); + mSpringAnim.addEndListener(onEndListener); + mSpringAnim.start(); })); } public void start() { mFlingAnim.start(); } + + public void end() { + mFlingAnim.cancel(); + if (mSpringAnim.canSkipToEnd()) { + mSpringAnim.skipToEnd(); + } + } }