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

Commit 8cb873d8 authored by Alex Chau's avatar Alex Chau Committed by Android (Google) Code Review
Browse files

Merge "Use bigger task size in app to overview carousel" into main

parents 9d927681 beb3053f
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -32,8 +32,11 @@
    <dimen name="overview_minimum_next_prev_size">50dp</dimen>

    <!--  Overview Task Views  -->
    <!--  The primary task thumbnail uses up to this much of the total screen height/width  -->
    <!--  The thumbnail uses up to this much of the total screen height/width in Overview -->
    <item name="overview_max_scale" format="float" type="dimen">0.7</item>
    <!--  The thumbnail should not go smaller than this much of the total screen height/width in
             tablet app to Overview carousel -->
    <item name="overview_carousel_min_scale" format="float" type="dimen">0.46</item>
    <!--  A touch target for icons, sometimes slightly larger than the icons themselves  -->
    <dimen name="task_thumbnail_icon_size">48dp</dimen>
    <!--  The icon size for the focused task, placed in center of touch target  -->
+5 −2
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static com.android.launcher3.BaseActivity.EVENT_DESTROYED;
import static com.android.launcher3.BaseActivity.EVENT_STARTED;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.Flags.enableGridOnlyOverview;
import static com.android.launcher3.LauncherPrefs.ALL_APPS_OVERVIEW_THRESHOLD;
import static com.android.launcher3.PagedView.INVALID_PAGE;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
@@ -2561,9 +2562,11 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
        }

        float scrollOffset = Math.abs(mRecentsView.getScrollOffset(mRecentsView.getCurrentPage()));
        Rect carouselTaskSize = enableGridOnlyOverview()
                ? mRecentsView.getLastComputedCarouselTaskSize()
                : mRecentsView.getLastComputedTaskSize();
        int maxScrollOffset = mRecentsView.getPagedOrientationHandler().getPrimaryValue(
                mRecentsView.getLastComputedTaskSize().width(),
                mRecentsView.getLastComputedTaskSize().height());
                carouselTaskSize.width(), carouselTaskSize.height());
        maxScrollOffset += mRecentsView.getPageSpacing();

        float maxScaleProgress =
+19 −2
Original line number Diff line number Diff line
@@ -261,6 +261,23 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
        }
    }

    /**
     * Calculates the taskView size for carousel during app to overview animation on tablets.
     */
    public final void calculateCarouselTaskSize(Context context, DeviceProfile dp, Rect outRect,
            PagedOrientationHandler orientedState) {
        if (dp.isTablet && dp.isGestureMode) {
            Resources res = context.getResources();
            float minScale = res.getFloat(R.dimen.overview_carousel_min_scale);
            Rect gridRect = new Rect();
            calculateGridSize(dp, context, gridRect);
            calculateTaskSizeInternal(context, dp, gridRect, minScale, Gravity.CENTER | Gravity.TOP,
                    outRect);
        } else {
            calculateTaskSize(context, dp, outRect, orientedState);
        }
    }

    private void calculateFocusTaskSize(Context context, DeviceProfile dp, Rect outRect) {
        Resources res = context.getResources();
        float maxScale = res.getFloat(R.dimen.overview_max_scale);
@@ -286,13 +303,13 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
    }

    private void calculateTaskSizeInternal(Context context, DeviceProfile dp,
            Rect potentialTaskRect, float maxScale, int gravity, Rect outRect) {
            Rect potentialTaskRect, float targetScale, int gravity, Rect outRect) {
        PointF taskDimension = getTaskDimension(context, dp);

        float scale = Math.min(
                potentialTaskRect.width() / taskDimension.x,
                potentialTaskRect.height() / taskDimension.y);
        scale = Math.min(scale, maxScale);
        scale = Math.min(scale, targetScale);
        int outWidth = Math.round(scale * taskDimension.x);
        int outHeight = Math.round(scale * taskDimension.y);

+7 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package com.android.quickstep.util;

import static com.android.app.animation.Interpolators.DECELERATE;
import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.Flags.enableGridOnlyOverview;
import static com.android.launcher3.LauncherPrefs.ALL_APPS_OVERVIEW_THRESHOLD;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
@@ -58,6 +59,7 @@ public class AnimatorControllerWithResistance {
        FROM_APP(0.75f, 0.5f, 1f, false),
        FROM_APP_TO_ALL_APPS(1f, 0.6f, 0.8f, false),
        FROM_APP_TABLET(1f, 0.7f, 1f, true),
        FROM_APP_TABLET_GRID_ONLY(1f, 1f, 1f, true),
        FROM_APP_TO_ALL_APPS_TABLET(1f, 0.5f, 0.5f, false),
        FROM_OVERVIEW(1f, 0.75f, 0.5f, false);

@@ -239,10 +241,10 @@ public class AnimatorControllerWithResistance {
        float stopResist =
                params.resistanceParams.stopScalingAtTop ? 1f - startRect.top / endRectF.top : 1f;
        final TimeInterpolator scaleInterpolator = t -> {
            if (t < startResist) {
            if (t <= startResist) {
                return t;
            }
            if (t > stopResist) {
            if (t >= stopResist) {
                return maxResist;
            }
            float resistProgress = Utilities.getProgress(t, startResist, stopResist);
@@ -304,6 +306,8 @@ public class AnimatorControllerWithResistance {
                resistanceParams =
                        recentsOrientedState.getActivityInterface().allowAllAppsFromOverview()
                                ? RecentsResistanceParams.FROM_APP_TO_ALL_APPS_TABLET
                                : enableGridOnlyOverview()
                                        ? RecentsResistanceParams.FROM_APP_TABLET_GRID_ONLY
                                        : RecentsResistanceParams.FROM_APP_TABLET;
            } else {
                resistanceParams =
+96 −12
Original line number Diff line number Diff line
@@ -38,10 +38,12 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;
import android.view.RemoteAnimationTarget;
import android.view.animation.Interpolator;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.app.animation.Interpolators;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
@@ -76,6 +78,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {

    private final Rect mTaskRect = new Rect();
    private final Rect mFullTaskSize = new Rect();
    private final Rect mCarouselTaskSize = new Rect();
    private PointF mPivotOverride = null;
    private final PointF mPivot = new PointF();
    private DeviceProfile mDp;
    @StagePosition
@@ -95,6 +99,11 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
    public final AnimatedFloat taskPrimaryTranslation = new AnimatedFloat();
    public final AnimatedFloat taskSecondaryTranslation = new AnimatedFloat();

    // Carousel properties
    public final AnimatedFloat carouselScale = new AnimatedFloat();
    public final AnimatedFloat carouselPrimaryTranslation = new AnimatedFloat();
    public final AnimatedFloat carouselSecondaryTranslation = new AnimatedFloat();

    // RecentsView properties
    public final AnimatedFloat recentsViewScale = new AnimatedFloat();
    public final AnimatedFloat fullScreenProgress = new AnimatedFloat();
@@ -109,9 +118,9 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
    private Boolean mDrawsBelowRecents = null;
    private boolean mIsGridTask;
    private boolean mIsDesktopTask;
    private boolean mScaleToCarouselTaskSize = false;
    private int mTaskRectTranslationX;
    private int mTaskRectTranslationY;
    private int mPivotOffsetX;

    public TaskViewSimulator(Context context, BaseActivityInterface sizeStrategy) {
        mContext = context;
@@ -124,6 +133,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
        mOrientationStateId = mOrientationState.getStateId();
        Resources resources = context.getResources();
        mIsRecentsRtl = mOrientationState.getOrientationHandler().getRecentsRtlSetting(resources);
        carouselScale.value = 1f;
    }

    /**
@@ -149,6 +159,11 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
                    mOrientationState.getOrientationHandler());
        }

        if (enableGridOnlyOverview()) {
            mSizeStrategy.calculateCarouselTaskSize(mContext, mDp, mCarouselTaskSize,
                    mOrientationState.getOrientationHandler());
        }

        if (mSplitBounds != null) {
            // The task rect changes according to the staged split task sizes, but recents
            // fullscreen scale and pivot remains the same since the task fits into the existing
@@ -193,9 +208,18 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
        }
        // Copy mFullTaskSize instead of updating it directly so it could be reused next time
        // without recalculating
        Rect scaleRect = new Rect(mFullTaskSize);
        scaleRect.offset(mTaskRectTranslationX + mPivotOffsetX, mTaskRectTranslationY);
        return mOrientationState.getFullScreenScaleAndPivot(scaleRect, mDp, mPivot);
        Rect scaleRect = new Rect();
        if (mScaleToCarouselTaskSize) {
            scaleRect.set(mCarouselTaskSize);
        } else {
            scaleRect.set(mFullTaskSize);
        }
        scaleRect.offset(mTaskRectTranslationX, mTaskRectTranslationY);
        float scale = mOrientationState.getFullScreenScaleAndPivot(scaleRect, mDp, mPivot);
        if (mPivotOverride != null) {
            mPivot.set(mPivotOverride);
        }
        return scale;
    }

    /**
@@ -278,14 +302,64 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
    /**
     * Adds animation for all the components corresponding to transition from an app to overview.
     */
    public void addAppToOverviewAnim(PendingAnimation pa, TimeInterpolator interpolator) {
    public void addAppToOverviewAnim(PendingAnimation pa, Interpolator interpolator) {
        pa.addFloat(fullScreenProgress, AnimatedFloat.VALUE, 1, 0, interpolator);
        if (enableGridOnlyOverview() && mDp.isTablet) {
            int translationXToMiddle = mDp.widthPx / 2 - mFullTaskSize.centerX();
            taskPrimaryTranslation.value = translationXToMiddle;
            mPivotOffsetX = translationXToMiddle;
        float fullScreenScale;
        if (enableGridOnlyOverview() && mDp.isTablet && mDp.isGestureMode) {
            // Move pivot to top right edge of the screen, to avoid task scaling down in opposite
            // direction of app window movement, otherwise the animation will wiggle left and right.
            // Also translate the app window to top right edge of the screen to simplify
            // calculations.
            taskPrimaryTranslation.value = mIsRecentsRtl
                    ? mDp.widthPx - mFullTaskSize.right
                    : -mFullTaskSize.left;
            taskSecondaryTranslation.value = -mFullTaskSize.top;
            mPivotOverride = new PointF(mIsRecentsRtl ? mDp.widthPx : 0, 0);

            // Scale down to the carousel and use the carousel Rect to calculate fullScreenScale.
            mScaleToCarouselTaskSize = true;
            carouselScale.value = mCarouselTaskSize.width() / (float) mFullTaskSize.width();
            fullScreenScale = getFullScreenScale();

            float carouselPrimaryTranslationTarget = mIsRecentsRtl
                    ? mCarouselTaskSize.right - mDp.widthPx
                    : mCarouselTaskSize.left;
            float carouselSecondaryTranslationTarget = mCarouselTaskSize.top;

            // Expected carousel position's center is in the middle, and invariant of
            // recentsViewScale.
            float exceptedCarouselCenterX = mCarouselTaskSize.centerX();
            // Animating carousel translations linearly will result in a curved path, therefore
            // we'll need to calculate the expected translation at each recentsView scale. Luckily
            // primary and secondary follow the same translation, and primary is used here due to
            // it being simpler.
            Interpolator carouselTranslationInterpolator = t -> {
                // recentsViewScale is calculated rather than using recentsViewScale.value, so that
                // this interpolator works independently even if recentsViewScale don't animate.
                float recentsViewScale =
                        Utilities.mapToRange(t, 0, 1, fullScreenScale, 1, Interpolators.LINEAR);
                // Without the translation, the app window will animate from fullscreen into top
                // right corner.
                float expectedTaskCenterX = mIsRecentsRtl
                        ? mDp.widthPx - mCarouselTaskSize.width() * recentsViewScale / 2f
                        : mCarouselTaskSize.width() * recentsViewScale / 2f;
                // Calculate the expected translation, then work back the animatedFraction that
                // results in this value.
                float carouselPrimaryTranslation =
                        (exceptedCarouselCenterX - expectedTaskCenterX) / recentsViewScale;
                return carouselPrimaryTranslation / carouselPrimaryTranslationTarget;
            };

            // Use addAnimatedFloat so this animation can later be canceled and animate to a
            // different value in RecentsView.onPrepareGestureEndAnimation.
            pa.addAnimatedFloat(carouselPrimaryTranslation, 0, carouselPrimaryTranslationTarget,
                    carouselTranslationInterpolator);
            pa.addAnimatedFloat(carouselSecondaryTranslation, 0, carouselSecondaryTranslationTarget,
                    carouselTranslationInterpolator);
        } else {
            fullScreenScale = getFullScreenScale();
        }
        pa.addFloat(recentsViewScale, AnimatedFloat.VALUE, getFullScreenScale(), 1, interpolator);
        pa.addFloat(recentsViewScale, AnimatedFloat.VALUE, fullScreenScale, 1, interpolator);
    }

    /**
@@ -382,7 +456,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {

        float fullScreenProgress = Utilities.boundToRange(this.fullScreenProgress.value, 0, 1);
        mCurrentFullscreenParams.setProgress(fullScreenProgress, recentsViewScale.value,
                /* taskViewScale= */1f);
                carouselScale.value);

        // Apply thumbnail matrix
        float taskWidth = mTaskRect.width();
@@ -396,6 +470,13 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
                taskPrimaryTranslation.value);
        mOrientationState.getOrientationHandler().setSecondary(mMatrix, MATRIX_POST_TRANSLATE,
                taskSecondaryTranslation.value);

        mMatrix.postScale(carouselScale.value, carouselScale.value, mPivot.x, mPivot.y);
        mOrientationState.getOrientationHandler().setPrimary(mMatrix, MATRIX_POST_TRANSLATE,
                carouselPrimaryTranslation.value);
        mOrientationState.getOrientationHandler().setSecondary(mMatrix, MATRIX_POST_TRANSLATE,
                carouselSecondaryTranslation.value);

        mOrientationState.getOrientationHandler().setPrimary(
                mMatrix, MATRIX_POST_TRANSLATE, recentsViewScroll.value);

@@ -420,15 +501,18 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
            return;
        }
        Log.d(TAG, "progress: " + fullScreenProgress
                + " carouselScale: " + carouselScale.value
                + " recentsViewScale: " + recentsViewScale.value
                + " crop: " + mTmpCropRect
                + " radius: " + getCurrentCornerRadius()
                + " taskW: " + taskWidth + " H: " + taskHeight
                + " taskRect: " + mTaskRect
                + " taskPrimaryT: " + taskPrimaryTranslation.value
                + " taskSecondaryT: " + taskSecondaryTranslation.value
                + " carouselPrimaryT: " + carouselPrimaryTranslation.value
                + " carouselSecondaryT: " + carouselSecondaryTranslation.value
                + " recentsPrimaryT: " + recentsViewPrimaryTranslation.value
                + " recentsSecondaryT: " + recentsViewSecondaryTranslation.value
                + " taskSecondaryT: " + taskSecondaryTranslation.value
                + " recentsScroll: " + recentsViewScroll.value
                + " pivot: " + mPivot
        );
Loading