Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f82fd492 authored by Jon Miranda's avatar Jon Miranda
Browse files

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
parent e0c5f5d0
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -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
+35 −2
Original line number Diff line number Diff line
@@ -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;
            }
        }

+9 −3
Original line number Diff line number Diff line
@@ -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