Fix bugs with quickstep springs.
* Listeners weren't getting called properly. We add one listener to the SpringbjectAnimator and then use that to dispatch to the other listeners. * We fast finish on both double swipe cases to prevent the shelf from ending in an invalid state. This causes a visual jump but this can be addressed in follow up CL. Bug: 111698021 Change-Id: Ifeb55da9dd253d062122a8e1577f94044f688641
This commit is contained in:
@@ -25,6 +25,7 @@ import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRE
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
|
||||
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.animation.ValueAnimator;
|
||||
@@ -82,7 +83,7 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
||||
if (mCurrentAnimation != null) {
|
||||
if (mFinishFastOnSecondTouch) {
|
||||
// TODO: Animate to finish instead.
|
||||
mCurrentAnimation.getAnimationPlayer().end();
|
||||
mCurrentAnimation.skipToEnd();
|
||||
}
|
||||
|
||||
AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
|
||||
@@ -241,7 +242,10 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
||||
private void handleFirstSwipeToOverview(final ValueAnimator animator,
|
||||
final long expectedDuration, final LauncherState targetState, final float velocity,
|
||||
final boolean isFling) {
|
||||
if (mFromState == NORMAL && mToState == OVERVIEW && targetState == OVERVIEW) {
|
||||
if (QUICKSTEP_SPRINGS.get() && mFromState == OVERVIEW && mToState == ALL_APPS
|
||||
&& targetState == OVERVIEW) {
|
||||
mFinishFastOnSecondTouch = true;
|
||||
} else if (mFromState == NORMAL && mToState == OVERVIEW && targetState == OVERVIEW) {
|
||||
mFinishFastOnSecondTouch = true;
|
||||
if (isFling && expectedDuration != 0) {
|
||||
// Update all apps interpolator to add a bit of overshoot starting from currFraction
|
||||
|
||||
@@ -80,6 +80,9 @@ public abstract class AnimatorPlaybackController implements ValueAnimator.Animat
|
||||
|
||||
private OnAnimationEndDispatcher mEndListener;
|
||||
private DynamicAnimation.OnAnimationEndListener mSpringEndListener;
|
||||
// We need this variable to ensure the end listener is called immediately, otherwise we run into
|
||||
// issues where the callback interferes with the states of the swipe detector.
|
||||
private boolean mSkipToEnd = false;
|
||||
|
||||
protected AnimatorPlaybackController(AnimatorSet anim, long duration,
|
||||
Runnable onCancelRunnable) {
|
||||
@@ -232,7 +235,11 @@ public abstract class AnimatorPlaybackController implements ValueAnimator.Animat
|
||||
}
|
||||
|
||||
private void dispatchOnStartRecursively(Animator animator) {
|
||||
for (AnimatorListener l : nonNullList(animator.getListeners())) {
|
||||
List<AnimatorListener> listeners = animator instanceof SpringObjectAnimator
|
||||
? nonNullList(((SpringObjectAnimator) animator).getSuperListeners())
|
||||
: nonNullList(animator.getListeners());
|
||||
|
||||
for (AnimatorListener l : listeners) {
|
||||
l.onAnimationStart(animator);
|
||||
}
|
||||
|
||||
@@ -280,6 +287,17 @@ public abstract class AnimatorPlaybackController implements ValueAnimator.Animat
|
||||
return mOnCancelRunnable;
|
||||
}
|
||||
|
||||
public void skipToEnd() {
|
||||
mSkipToEnd = true;
|
||||
for (SpringAnimation spring : mSprings) {
|
||||
if (spring.canSkipToEnd()) {
|
||||
spring.skipToEnd();
|
||||
}
|
||||
}
|
||||
mAnimationPlayer.end();
|
||||
mSkipToEnd = false;
|
||||
}
|
||||
|
||||
public static class AnimatorPlaybackControllerVL extends AnimatorPlaybackController {
|
||||
|
||||
private final ValueAnimator[] mChildAnimations;
|
||||
@@ -343,19 +361,34 @@ public abstract class AnimatorPlaybackController implements ValueAnimator.Animat
|
||||
*/
|
||||
private class OnAnimationEndDispatcher extends AnimationSuccessListener {
|
||||
|
||||
boolean mAnimatorDone = false;
|
||||
boolean mSpringsDone = false;
|
||||
boolean mDispatched = false;
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mCancelled = false;
|
||||
mDispatched = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
if (mSprings.isEmpty()) {
|
||||
mSpringsDone = mAnimatorDone = true;
|
||||
}
|
||||
if (isAnySpringRunning()) {
|
||||
mAnimatorDone = true;
|
||||
} else {
|
||||
mSpringsDone = true;
|
||||
}
|
||||
|
||||
// We wait for the spring (if any) to finish running before completing the end callback.
|
||||
if (mSprings.isEmpty() || !isAnySpringRunning()) {
|
||||
if (!mDispatched && (mSkipToEnd || (mAnimatorDone && mSpringsDone))) {
|
||||
dispatchOnEndRecursively(mAnim);
|
||||
if (mEndAction != null) {
|
||||
mEndAction.run();
|
||||
}
|
||||
mDispatched = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,9 @@ public class SpringObjectAnimator<T extends ProgressInterface> extends ValueAnim
|
||||
mListeners = new ArrayList<>();
|
||||
setFloatValues(values);
|
||||
|
||||
mObjectAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
// We use this listener and track mListeners so that we can sync the animator and spring
|
||||
// listeners.
|
||||
super.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mAnimatorEnded = false;
|
||||
@@ -94,7 +96,7 @@ public class SpringObjectAnimator<T extends ProgressInterface> extends ValueAnim
|
||||
for (AnimatorListener l : mListeners) {
|
||||
l.onAnimationCancel(animation);
|
||||
}
|
||||
mSpring.animateToFinalPosition(mObject.getProgress());
|
||||
mSpring.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -145,6 +147,10 @@ public class SpringObjectAnimator<T extends ProgressInterface> extends ValueAnim
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
public ArrayList<AnimatorListener> getSuperListeners() {
|
||||
return super.getListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<AnimatorListener> getListeners() {
|
||||
return mListeners;
|
||||
@@ -167,8 +173,8 @@ public class SpringObjectAnimator<T extends ProgressInterface> extends ValueAnim
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
mSpring.animateToFinalPosition(mObject.getProgress());
|
||||
mObjectAnimator.cancel();
|
||||
mSpring.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user