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

Commit cf03d044 authored by Jeremy Sim's avatar Jeremy Sim Committed by Android (Google) Code Review
Browse files

Merge "Update animations for TM-QPR: Overview > OverviewSplitSelect transition" into tm-qpr-dev

parents 4b972af5 a50bb390
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -188,6 +188,9 @@ public class QuickstepAtomicAnimationFactory extends
            AllAppsSwipeController.applyAllAppsToNormalConfig(mActivity, config);
        } else if (fromState == NORMAL && toState == ALL_APPS) {
            AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mActivity, config);
        } else if (fromState == OVERVIEW && toState == OVERVIEW_SPLIT_SELECT) {
            config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE,
                    clampToProgress(LINEAR, 0, 0.167f));
        }
    }
}
+9 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.launcher3.uioverrides.states;

import android.content.Context;

import com.android.launcher3.Launcher;
import com.android.quickstep.views.RecentsView;

@@ -24,6 +26,8 @@ import com.android.quickstep.views.RecentsView;
 * pinned and user is selecting the second one
 */
public class SplitScreenSelectState extends OverviewState {
    private static final int OVERVIEW_SPLIT_SELECT_SLIDE_IN_DURATION = 500;

    public SplitScreenSelectState(int id) {
        super(id);
    }
@@ -38,4 +42,9 @@ public class SplitScreenSelectState extends OverviewState {
        RecentsView recentsView = launcher.getOverviewPanel();
        return recentsView.getSplitSelectTranslation();
    }

    @Override
    public int getTransitionDuration(Context context, boolean isToState) {
        return OVERVIEW_SPLIT_SELECT_SLIDE_IN_DURATION;
    }
}
+18 −8
Original line number Diff line number Diff line
@@ -2,8 +2,9 @@ package com.android.quickstep.views;

import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.anim.Interpolators.FASTER_OUT_SLOWER_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.clampToProgress;

import android.animation.ValueAnimator;
import android.content.Context;
@@ -200,10 +201,16 @@ public class FloatingTaskView extends FrameLayout {
        RectF floatingTaskViewBounds = new RectF();

        if (fadeWithThumbnail) {
            animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ALPHA_FLOAT,
                    0, 1, ACCEL);
            // FloatingTaskThumbnailView: thumbnail fades out to transparent
            animation.addFloat(mThumbnailView, LauncherAnimUtils.VIEW_ALPHA,
                    1, 0, DEACCEL_3);
                    1, 0, clampToProgress(LINEAR, 0, 0.267f));

            // SplitPlaceholderView: gray background fades in at the same time, then new icon fades
            // in
            animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ALPHA_FLOAT,
                    0, 1, clampToProgress(LINEAR, 0, 0.267f));
            animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ICON_ALPHA,
                    0, 1, clampToProgress(LINEAR, 0.333f, 0.5f));
        } else if (isStagedTask) {
            // Fade in the placeholder view when split is initiated from homescreen / all apps
            // icons.
@@ -214,12 +221,15 @@ public class FloatingTaskView extends FrameLayout {
        }

        MultiValueUpdateListener listener = new MultiValueUpdateListener() {
            final FloatProp mDx = new FloatProp(0, prop.dX, 0, animDuration, LINEAR);
            final FloatProp mDy = new FloatProp(0, prop.dY, 0, animDuration, LINEAR);
            // SplitPlaceholderView: rectangle translates and stretches to new position
            final FloatProp mDx = new FloatProp(0, prop.dX, 0, animDuration,
                    clampToProgress(FASTER_OUT_SLOWER_IN, 0, 0.833f));
            final FloatProp mDy = new FloatProp(0, prop.dY, 0, animDuration,
                    clampToProgress(FASTER_OUT_SLOWER_IN, 0, 0.833f));
            final FloatProp mTaskViewScaleX = new FloatProp(1f, prop.finalTaskViewScaleX, 0,
                    animDuration, LINEAR);
                    animDuration, clampToProgress(FASTER_OUT_SLOWER_IN, 0, 0.833f));
            final FloatProp mTaskViewScaleY = new FloatProp(1f, prop.finalTaskViewScaleY, 0,
                    animDuration, LINEAR);
                    animDuration, clampToProgress(FASTER_OUT_SLOWER_IN, 0, 0.833f));
            @Override
            public void onUpdate(float percent, boolean initOnly) {
                // Calculate the icon position.
+77 −15
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
import static com.android.launcher3.anim.Interpolators.LINEAR;
@@ -113,6 +114,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.core.graphics.ColorUtils;
import androidx.dynamicanimation.animation.SpringForce;

import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseActivity.MultiWindowModeChangedListener;
@@ -125,6 +127,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.SpringAnimationBuilder;
import com.android.launcher3.anim.SpringProperty;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
@@ -442,6 +445,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
    private static final float ANIMATION_DISMISS_PROGRESS_MIDPOINT = 0.5f;
    private static final float END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.75f;

    private static final float INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.133f;
    private static final float ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.033f;

    private static final float SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE = 0.15f;

    protected final RecentsOrientedState mOrientationState;
@@ -2825,7 +2831,20 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T

        RectF startingTaskRect = new RectF();
        if (mSplitHiddenTaskView != null) {
            mSplitHiddenTaskView.setVisibility(INVISIBLE);
            // Split staging is initiated, hide the original TaskView except for the icon (which
            // needs to animate out over time)
            // If needed, visibility should be toggled back on in resetFromSplitSelectionState().
            for (int i = 0; i < mSplitHiddenTaskView.getChildCount(); i++) {
                View child = mSplitHiddenTaskView.getChildAt(i);
                if (child != mSplitHiddenTaskView.mIconView) {
                    child.setVisibility(INVISIBLE);
                }
            }

            // Icon animates out over time
            anim.addFloat(mSplitHiddenTaskView, TaskView.ICON_ALPHA, 1, 0,
                    clampToProgress(LINEAR, 0, 0.167f));

            mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
                    mSplitHiddenTaskView.getThumbnail(),
                    mSplitHiddenTaskView.getThumbnail().getThumbnail(),
@@ -2842,9 +2861,15 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
                    false /* fadeWithThumbnail */, true /* isStagedTask */);
        }

        // SplitInstructionsView: animate in
        mSplitInstructionsView = SplitInstructionsView.getSplitInstructionsView(mActivity);
        mSplitInstructionsView.setAlpha(0);
        anim.addFloat(mSplitInstructionsView, SplitInstructionsView.ALPHA_FLOAT, 0, 1, ACCEL);
        anim.addFloat(mSplitInstructionsView, SplitInstructionsView.CONTAINER_ALPHA, 0, 1,
                clampToProgress(LINEAR, 0, 0.167f));
        anim.addFloat(mSplitInstructionsView, SplitInstructionsView.TEXT_ALPHA, 0, 1,
                clampToProgress(LINEAR, 0.1f, 0.267f));
        anim.addFloat(mSplitInstructionsView, mSplitInstructionsView.UNFOLD, 0.1f, 1,
                clampToProgress(EMPHASIZED_DECELERATE, 0, 0.667f));

        InteractionJankMonitorWrapper.begin(this,
                InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "First tile selected");
@@ -3124,11 +3149,22 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
                // Animate task with index >= dismissed index and in the same row as the
                // dismissed index or next focused index. Offset successive task dismissal
                // durations for a staggered effect.
                float animationStartProgress = Utilities.boundToRange(
                distanceFromDismissedTask++;
                // If user is initiating splitscreen from the focused (large) task, we use a
                // spring-based animation and timings. For other, smaller, repositions, we currently
                // fall back on a less complicated linear animation and timings.
                float animationStartProgress = isFocusedTaskDismissed && nextFocusedTaskView == null
                        ? Utilities.boundToRange(
                                INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
                                        + ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
                                        * (int) Math.ceil(distanceFromDismissedTask / 2f), 0f,
                        dismissTranslationInterpolationEnd)
                        : Utilities.boundToRange(
                                INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
                                        + ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
                                * ++distanceFromDismissedTask, 0f,
                                        * distanceFromDismissedTask, 0f,
                                dismissTranslationInterpolationEnd);

                if (taskView == nextFocusedTaskView) {
                    // Enlarge the task to be focused next, and translate into focus position.
                    float scale = mTaskWidth / (float) mLastComputedGridTaskSize.width();
@@ -3163,8 +3199,31 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
                            primaryTranslation +=
                                    mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
                        }
                    }

                        // Transitioning to split select -- set up staggered spring animation for
                        // other TaskViews.
                        Animator taskSlideIn = new SpringAnimationBuilder(taskView.mActivity)
                                .setDampingRatio(0.85f)
                                .setStiffness(SpringForce.STIFFNESS_LOW)
                                .setEndValue(mIsRtl ? primaryTranslation : -primaryTranslation)
                                .setStartValue(
                                        taskView.getPrimaryDismissTranslationProperty()
                                                .get(taskView)
                                )
                                .build(taskView, taskView.getPrimaryDismissTranslationProperty());
                        long taskSlideInDuration = taskSlideIn.getDuration();
                        anim.add(taskSlideIn);
                        taskSlideIn
                                .setDuration(taskSlideInDuration)
                                .setStartDelay(
                                        Math.round(animationStartProgress * anim.getDuration()));
                    } else {
                        // Task was dismissed individually -- translate other TaskViews to fill the
                        // vacant space.

                        // TODO (b/242075836): This dismiss animation uses a linear transition.
                        // When the above bug is fixed, it can use the same (nicer) spring
                        // transition as the focused task split case above.
                        anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(),
                                mIsRtl ? primaryTranslation : -primaryTranslation,
                                clampToProgress(LINEAR, animationStartProgress,
@@ -3172,6 +3231,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
                    }
                }
            }
        }

        if (needsCurveUpdates) {
            anim.addOnFrameCallback(this::updateCurveProperties);
@@ -3189,7 +3249,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        final boolean finalCloseGapBetweenClearAll = closeGapBetweenClearAll;
        final boolean finalSnapToLastTask = snapToLastTask;
        final boolean finalIsFocusedTaskDismissed = isFocusedTaskDismissed;
        mPendingAnimation.addEndListener(new Consumer<Boolean>() {

        Consumer endConsumer = new Consumer<Boolean>() {
            @Override
            public void accept(Boolean success) {
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile
@@ -3399,7 +3460,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
                onDismissAnimationEnds();
                mPendingAnimation = null;
            }
        });
        };

        mPendingAnimation.addListener(AnimatorListeners.forEndCallback(endConsumer));
        return anim;
    }

@@ -4220,7 +4283,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        resetTaskVisuals();
        mSplitHiddenTaskViewIndex = -1;
        if (mSplitHiddenTaskView != null) {
            mSplitHiddenTaskView.setVisibility(VISIBLE);
            mSplitHiddenTaskView = null;
        }
    }
+33 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;

import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
@@ -40,9 +41,10 @@ import com.android.launcher3.util.DisplayController;
 */
public class SplitInstructionsView extends FrameLayout {
    private final StatefulActivity mLauncher;
    private AppCompatTextView mTextView;

    public static final FloatProperty<SplitInstructionsView> ALPHA_FLOAT =
            new FloatProperty<SplitInstructionsView>("SplitInstructionsAlpha") {
    public static final FloatProperty<SplitInstructionsView> CONTAINER_ALPHA =
            new FloatProperty<SplitInstructionsView>("SplitInstructionsContainerAlpha") {
                @Override
                public void setValue(SplitInstructionsView splitInstructionsView, float v) {
                    splitInstructionsView.setVisibility(v != 0 ? VISIBLE : GONE);
@@ -55,6 +57,32 @@ public class SplitInstructionsView extends FrameLayout {
                }
            };

    public static final FloatProperty<SplitInstructionsView> UNFOLD =
            new FloatProperty<SplitInstructionsView>("SplitInstructionsUnfold") {
                @Override
                public void setValue(SplitInstructionsView splitInstructionsView, float v) {
                    splitInstructionsView.setScaleY(v);
                }

                @Override
                public Float get(SplitInstructionsView splitInstructionsView) {
                    return splitInstructionsView.getScaleY();
                }
            };

    public static final FloatProperty<SplitInstructionsView> TEXT_ALPHA =
            new FloatProperty<SplitInstructionsView>("SplitInstructionsTextAlpha") {
                @Override
                public void setValue(SplitInstructionsView splitInstructionsView, float v) {
                    splitInstructionsView.mTextView.setAlpha(v);
                }

                @Override
                public Float get(SplitInstructionsView splitInstructionsView) {
                    return splitInstructionsView.mTextView.getAlpha();
                }
            };

    public SplitInstructionsView(Context context) {
        this(context, null);
    }
@@ -77,6 +105,9 @@ public class SplitInstructionsView extends FrameLayout {
                        false
                );

        splitInstructionsView.mTextView = splitInstructionsView.findViewById(
                R.id.split_instructions_text);

        dragLayer.addView(splitInstructionsView);
        return splitInstructionsView;
    }
Loading