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

Commit 56b247da authored by Tony Wickham's avatar Tony Wickham Committed by Android (Google) Code Review
Browse files

Merge "Add atomic recents animation while swiping up" into ub-launcher3-edmonton

parents f69f0c2b 6becf7c0
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ public class AllAppsState extends LauncherState {

    @Override
    public float[] getOverviewScaleAndTranslationYFactor(Launcher launcher) {
        return new float[] {1f, -0.2f};
        return new float[] {0.9f, -0.2f};
    }

    @Override
+4 −3
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ import android.view.MotionEvent;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationComponents;
import com.android.launcher3.touch.AbstractStateChangeTouchController;
import com.android.launcher3.touch.SwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -56,11 +57,11 @@ public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchContro
    }

    @Override
    protected float initCurrentAnimation() {
    protected float initCurrentAnimation(@AnimationComponents int animComponent) {
        float range = getShiftRange();
        long maxAccuracy = (long) (2 * range);
        mCurrentAnimation = mLauncher.getStateManager()
                .createAnimationToNewWorkspace(mToState, maxAccuracy);
        mCurrentAnimation = mLauncher.getStateManager().createAnimationToNewWorkspace(mToState,
                maxAccuracy, animComponent);
        return (mLauncher.getDeviceProfile().isSeascape() ? 2 : -2) / range;
    }

+7 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Workspace;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.views.RecentsView;
@@ -47,8 +48,12 @@ public class OverviewState extends LauncherState {

    @Override
    public float[] getWorkspaceScaleAndTranslation(Launcher launcher) {
        // TODO: provide a valid value
        return new float[]{1, 0, -launcher.getDeviceProfile().hotseatBarSizePx / 2};
        RecentsView recentsView = launcher.getOverviewPanel();
        Workspace workspace = launcher.getWorkspace();
        recentsView.getTaskSize(sTempRect);
        float scale = (float) sTempRect.width() / workspace.getWidth();
        float parallaxFactor = 0.4f;
        return new float[]{scale, 0, -getDefaultSwipeHeight(launcher) * parallaxFactor};
    }

    @Override
+21 −94
Original line number Diff line number Diff line
@@ -18,20 +18,20 @@ package com.android.launcher3.uioverrides;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATION;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;

import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
import android.view.animation.OvershootInterpolator;

import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationComponents;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
@@ -52,43 +52,11 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr

    private static final String TAG = "PortraitStatesTouchCtrl";

    private static final float TOTAL_DISTANCE_MULTIPLIER = 3f;
    private static final float LINEAR_SCALE_LIMIT = 1 / TOTAL_DISTANCE_MULTIPLIER;

    // Must be greater than LINEAR_SCALE_LIMIT;
    private static final float MAXIMUM_DISTANCE_FACTOR = 0.9f;

    // Maximum amount to overshoot.
    private static final float MAX_OVERSHOOT = 0.3f;

    private static final double PI_BY_2 = Math.PI / 2;

    private InterpolatorWrapper mAllAppsInterpolatorWrapper = new InterpolatorWrapper();

    // If true, we will finish the current animation instantly on second touch.
    private boolean mFinishFastOnSecondTouch;

    private final Interpolator mAllAppsDampedInterpolator = new Interpolator() {

        private final double mAngleMultiplier = Math.PI /
                (2 * (MAXIMUM_DISTANCE_FACTOR - LINEAR_SCALE_LIMIT));

        @Override
        public float getInterpolation(float v) {
            if (v <= LINEAR_SCALE_LIMIT) {
                return v * TOTAL_DISTANCE_MULTIPLIER;
            }
            float overshoot = (v - LINEAR_SCALE_LIMIT);
            return (float) (1 + MAX_OVERSHOOT * Math.sin(overshoot * mAngleMultiplier));
        }
    };

    private final Interpolator mOverviewBoundInterpolator = (v) -> {
            if (v >= MAXIMUM_DISTANCE_FACTOR) {
                return 1;
            }
            return FAST_OUT_SLOW_IN.getInterpolation(v / MAXIMUM_DISTANCE_FACTOR);
    };

    public PortraitStatesTouchController(Launcher l) {
        super(l, SwipeDetector.VERTICAL);
@@ -144,17 +112,16 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
    }

    private AnimatorSetBuilder getNormalToOverviewAnimation() {
        mAllAppsInterpolatorWrapper.baseInterpolator = mAllAppsDampedInterpolator;
        mAllAppsInterpolatorWrapper.baseInterpolator = LINEAR;

        AnimatorSetBuilder builder = new AnimatorSetBuilder();
        builder.setInterpolator(ANIM_VERTICAL_PROGRESS, mAllAppsInterpolatorWrapper);

        builder.setInterpolator(ANIM_OVERVIEW_TRANSLATION, mOverviewBoundInterpolator);
        return builder;
    }

    @Override
    protected float initCurrentAnimation() {
    protected float initCurrentAnimation(@AnimationComponents int animComponents) {
        float range = getShiftRange();
        long maxAccuracy = (long) (2 * range);

@@ -167,7 +134,6 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr

        if (mFromState == NORMAL && mToState == OVERVIEW && totalShift != 0) {
            builder = getNormalToOverviewAnimation();
            totalShift = totalShift * TOTAL_DISTANCE_MULTIPLIER;
        } else {
            builder = new AnimatorSetBuilder();
        }
@@ -190,7 +156,8 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
            mLauncher.getStateManager().setCurrentUserControlledAnimation(mCurrentAnimation);
        } else {
            mCurrentAnimation = mLauncher.getStateManager()
                    .createAnimationToNewWorkspace(mToState, builder, maxAccuracy, this::clearState);
                    .createAnimationToNewWorkspace(mToState, builder, maxAccuracy, this::clearState,
                            animComponents);
        }

        if (totalShift == 0) {
@@ -210,9 +177,9 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
    @Override
    protected void updateSwipeCompleteAnimation(ValueAnimator animator, long expectedDuration,
            LauncherState targetState, float velocity, boolean isFling) {
        handleFirstSwipeToOverview(animator, expectedDuration, targetState, velocity, isFling);
        super.updateSwipeCompleteAnimation(animator, expectedDuration, targetState,
                velocity, isFling);
        handleFirstSwipeToOverview(animator, expectedDuration, targetState, velocity, isFling);
    }

    private void handleFirstSwipeToOverview(final ValueAnimator animator,
@@ -220,63 +187,23 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
            final boolean isFling) {
        if (mFromState == NORMAL && mToState == OVERVIEW && targetState == OVERVIEW) {
            mFinishFastOnSecondTouch = true;

            // Update all apps interpolator
            float currentFraction = mCurrentAnimation.getProgressFraction();
            float absVelocity = Math.abs(velocity);
            float currentValue = mAllAppsDampedInterpolator.getInterpolation(currentFraction);

            if (isFling && absVelocity > 1 && currentFraction < LINEAR_SCALE_LIMIT) {

                // TODO: Clean up these magic calculations
                // Linearly interpolate the max value based on the velocity.
                float maxValue = Math.max(absVelocity > 4 ? 1 + MAX_OVERSHOOT :
                                1 + (absVelocity - 1) * MAX_OVERSHOOT / 3,
                        currentValue);
                double angleToPeak = PI_BY_2 - Math.asin(currentValue / maxValue);

                if (expectedDuration != 0 && angleToPeak != 0) {

                    float distanceLeft = 1 - currentFraction;
                    mAllAppsInterpolatorWrapper.baseInterpolator = (f) -> {
                        float scaledF = (f - currentFraction) / distanceLeft;

                        if (scaledF < 0.5f) {
                            double angle = PI_BY_2 - angleToPeak + scaledF * angleToPeak / 0.5f;
                            return (float) (maxValue * Math.sin(angle));
                        }

                        scaledF = ((scaledF - .5f) / .5f);
                        double angle = PI_BY_2 + 3 * scaledF * PI_BY_2;
                        float amplitude = (1 - scaledF) * (1 - scaledF) * (maxValue - 1);
                        return 1 + (float) (amplitude * Math.sin(angle));
                    };

                    animator.setDuration(expectedDuration).setInterpolator(LINEAR);
                    return;
                }
            }

            if (currentFraction < LINEAR_SCALE_LIMIT) {
                mAllAppsInterpolatorWrapper.baseInterpolator = LINEAR;
                return;
            if (isFling && expectedDuration != 0) {
                // Update all apps interpolator to add a bit of overshoot starting from currFraction
                final float currFraction = mCurrentAnimation.getProgressFraction();
                mAllAppsInterpolatorWrapper.baseInterpolator
                        = new OvershootInterpolator(Math.min(Math.abs(velocity) / 3, 3f)) {
                    @Override
                    public float getInterpolation(float t) {
                        return super.getInterpolation(t) + ((1 - t) * currFraction);
                    }
            float extraValue = mAllAppsDampedInterpolator.getInterpolation(currentFraction) - 1;
            float distanceLeft = 1 - currentFraction;

            animator.setFloatValues(currentFraction, 1);
            mAllAppsInterpolatorWrapper.baseInterpolator = (f) -> {
                float scaledF = (f - currentFraction) / distanceLeft;

                double angle = scaledF * 1.5 * Math.PI;
                float amplitude = (1 - scaledF) * (1 - scaledF) * extraValue;
                return 1 + (float) (amplitude * Math.sin(angle));
                };
            animator.setDuration(200).setInterpolator(LINEAR);
            return;
                animator.setFloatValues(0, 1);
                animator.setDuration(Math.max(expectedDuration, 300)).setInterpolator(LINEAR);
            }
        } else {
            mFinishFastOnSecondTouch = false;
        }
    }

    @Override
    protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
+6 −5
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
 */
package com.android.launcher3.uioverrides;

import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATION;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_Y_FACTOR;
@@ -63,12 +62,14 @@ public class RecentsViewStateController implements StateHandler {
    @Override
    public void setStateWithAnimation(final LauncherState toState,
            AnimatorSetBuilder builder, AnimationConfig config) {
        if (!config.playAtomicComponent()) {
            // The entire recents animation is played atomically.
            return;
        }
        PropertySetter setter = config.getPropertySetter(builder);
        float[] scaleTranslationYFactor = toState.getOverviewScaleAndTranslationYFactor(mLauncher);
        setter.setFloat(mRecentsView, ADJACENT_SCALE, scaleTranslationYFactor[0],
                builder.getInterpolator(ANIM_OVERVIEW_TRANSLATION, LINEAR));
        setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1],
                builder.getInterpolator(ANIM_OVERVIEW_TRANSLATION, LINEAR));
        setter.setFloat(mRecentsView, ADJACENT_SCALE, scaleTranslationYFactor[0], LINEAR);
        setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1], LINEAR);
        setter.setFloat(mRecentsViewContainer, CONTENT_ALPHA, toState.overviewUi ? 1 : 0,
                AGGRESSIVE_EASE_IN_OUT);

Loading