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
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 3797e87..7076f58 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 @@
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 @@
@UiThread
private InputConsumer createNewInputProxyHandler() {
- mCurrentShift.finishAnimation();
+ endRunningWindowAnim();
if (mLauncherTransitionController != null) {
mLauncherTransitionController.getAnimationPlayer().end();
}
@@ -817,6 +819,12 @@
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 @@
}
});
windowAnim.start(velocityPxPerMs);
+ mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim);
mLauncherTransitionController = null;
} else {
ValueAnimator windowAnim = mCurrentShift.animateToValue(start, end);
@@ -1002,6 +1011,7 @@
}
});
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 @@
false /* animate */, true /* freezeTaskList */);
});
}
- TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", false);
+ TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", true);
doLogGesture(NEW_TASK);
reset();
}
@@ -1133,7 +1143,7 @@
}
private void invalidateHandler() {
- mCurrentShift.finishAnimation();
+ endRunningWindowAnim();
if (mGestureEndCallback != null) {
mGestureEndCallback.run();
@@ -1281,4 +1291,16 @@
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 2edeb3a..7159e7c 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.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 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 @@
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 @@
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 @@
}
});
- 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 @@
}
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 3d21d82..45d49e8 100644
--- a/src/com/android/launcher3/anim/FlingSpringAnim.java
+++ b/src/com/android/launcher3/anim/FlingSpringAnim.java
@@ -34,6 +34,7 @@
private static final float SPRING_DAMPING = SpringForce.DAMPING_RATIO_LOW_BOUNCY;
private final FlingAnimation mFlingAnim;
+ private SpringAnimation mSpringAnim;
public <K> FlingSpringAnim(K object, FloatPropertyCompat<K> property, float startPosition,
float targetPosition, float startVelocity, OnAnimationEndListener onEndListener) {
@@ -44,17 +45,24 @@
.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();
+ }
+ }
}