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

Commit 9594c698 authored by Alex Chau's avatar Alex Chau
Browse files

Handle page offset for grid overview

- Use TaskView's actual position with grid/fullscreen translation considered for taskPosition calculation
- Shift taskPosition by midpoint scroll, and no longer assumes midpoint is on middle of the screen
- Handle situation that TaskView is on left/right of midpoint, making the calculation generic to be able to handle grid situation

Bug: 175939487
Test: Launch modal view with wide/, RTL/non-RTL, orientation/simulated landscape combinations
Change-Id: Idd0cc9c5e24f453d830e1420319a38d3d784270d
parent def4ff15
Loading
Loading
Loading
Loading
+95 −39
Original line number Diff line number Diff line
@@ -270,7 +270,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
                public void setValue(RecentsView view, float scale) {
                    view.setScaleX(scale);
                    view.setScaleY(scale);
                    view.mLastComputedTaskPushOutDistance = null;
                    view.mLastComputedTaskStartPushOutDistance = null;
                    view.mLastComputedTaskEndPushOutDistance = null;
                    view.mLiveTileTaskViewSimulator.recentsViewScale.value = scale;
                    view.updatePageOffsets();
                    view.setTaskViewsResistanceTranslation(view.mTaskViewsSecondaryTranslation);
@@ -308,7 +309,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
    protected final Rect mLastComputedGridSize = new Rect();
    protected final Rect mLastComputedGridTaskSize = new Rect();
    // How much a task that is directly offscreen will be pushed out due to RecentsView scale/pivot.
    protected Float mLastComputedTaskPushOutDistance = null;
    protected Float mLastComputedTaskStartPushOutDistance = null;
    protected Float mLastComputedTaskEndPushOutDistance = null;
    protected boolean mEnableDrawingLiveTile = false;
    protected final Rect mTempRect = new Rect();
    protected final RectF mTempRectF = new RectF();
@@ -2467,7 +2469,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        setPivotX(mTempPointF.x);
        setPivotY(mTempPointF.y);
        setTaskModalness(mTaskModalness);
        mLastComputedTaskPushOutDistance = null;
        mLastComputedTaskStartPushOutDistance = null;
        mLastComputedTaskEndPushOutDistance = null;
        updatePageOffsets();
        setImportantForAccessibility(isModal() ? IMPORTANT_FOR_ACCESSIBILITY_NO
                : IMPORTANT_FOR_ACCESSIBILITY_AUTO);
@@ -2476,10 +2479,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
    private void updatePageOffsets() {
        float offset = mAdjacentPageOffset;
        float modalOffset = ACCEL_0_75.getInterpolation(mTaskModalness);
        if (mIsRtl) {
            offset = -offset;
            modalOffset = -modalOffset;
        }
        int count = getChildCount();

        TaskView runningTask = mRunningTaskId == -1 || !mRunningTaskTileHidden
@@ -2495,13 +2494,27 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
                ? getOffsetSize(midpoint + 1, midpoint, offset)
                : 0;

        boolean showAsGrid = showAsGrid();
        float modalMidpointOffsetSize = 0;
        float modalLeftOffsetSize = modalMidpoint - 1 >= 0
                ? -getOffsetSize(modalMidpoint - 1, modalMidpoint, modalOffset)
        float modalLeftOffsetSize = 0;
        float modalRightOffsetSize = 0;
        float gridOffsetSize = 0;

        if (showAsGrid) {
            // In grid, we only focus the task on the side. The reference index used for offset
            // calculation is the task directly next to the focus task in the grid.
            int referenceIndex = modalMidpoint == 0 ? 1 : 0;
            gridOffsetSize = referenceIndex < count
                    ? getOffsetSize(referenceIndex, modalMidpoint, modalOffset)
                    : 0;
        float modalRightOffsetSize = modalMidpoint + 1 < count
        } else {
            modalLeftOffsetSize = modalMidpoint - 1 >= 0
                    ? getOffsetSize(modalMidpoint - 1, modalMidpoint, modalOffset)
                    : 0;
            modalRightOffsetSize = modalMidpoint + 1 < count
                    ? getOffsetSize(modalMidpoint + 1, modalMidpoint, modalOffset)
                    : 0;
        }

        for (int i = 0; i < count; i++) {
            float translation = i == midpoint
@@ -2511,20 +2524,36 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
                            : rightOffsetSize;
            float modalTranslation = i == modalMidpoint
                    ? modalMidpointOffsetSize
                    : i < modalMidpoint
                            ? modalLeftOffsetSize
                            : modalRightOffsetSize;
                    : showAsGrid
                            ? gridOffsetSize
                            : i < modalMidpoint ? modalLeftOffsetSize : modalRightOffsetSize;
            float totalTranslation = translation + modalTranslation;
            View child = getChildAt(i);
            FloatProperty translationProperty = child instanceof TaskView
                    ? ((TaskView) child).getPrimaryTaskOffsetTranslationProperty()
                    : mOrientationHandler.getPrimaryViewTranslate();
            translationProperty.set(child,
                    totalTranslation * mOrientationHandler.getPrimaryTranslationDirectionFactor());
            translationProperty.set(child, totalTranslation);
        }
        updateCurveProperties();
    }

    /**
     * Computes the child position with persistent translation considered (see
     * {@link TaskView#getPersistentTranslationX()}.
     */
    private void getPersistentChildPosition(int childIndex, int midPointScroll, RectF outRect) {
        View child = getChildAt(childIndex);
        outRect.set(child.getLeft(), child.getTop(), child.getRight(), child.getBottom());
        if (child instanceof TaskView) {
            TaskView taskView = (TaskView) child;
            outRect.offset(taskView.getPersistentTranslationX(),
                    taskView.getPersistentTranslationY());
            outRect.top += mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
        }
        outRect.offset(mOrientationHandler.getPrimaryValue(-midPointScroll, 0),
                mOrientationHandler.getSecondaryValue(-midPointScroll, 0));
    }

    /**
     * Computes the distance to offset the given child such that it is completely offscreen when
     * translating away from the given midpoint.
@@ -2535,33 +2564,60 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
            // Don't bother calculating everything below if we won't offset anyway.
            return 0;
        }

        // First, get the position of the task relative to the midpoint. If there is no midpoint
        // then we just use the normal (centered) task position.
        mTempRectF.set(mLastComputedTaskSize);
        RectF taskPosition = mTempRectF;
        float desiredLeft = getWidth();
        // Used to calculate the scale of the task view based on its new offset.
        // Whether the task should be shifted to start direction (i.e. left edge for portrait, top
        // edge for landscape/seascape).
        boolean isStartShift;
        if (midpointIndex > -1) {
            // When there is a midpoint reference task, adjacent tasks have less distance to travel
            // to reach offscreen. Offset the task position to the task's starting point.
            View child = getChildAt(childIndex);
            View midpointChild = getChildAt(midpointIndex);
            int distanceFromMidpoint = Math.abs(mOrientationHandler.getChildStart(child)
                    - mOrientationHandler.getChildStart(midpointChild)
                    + getDisplacementFromScreenCenter(midpointIndex));
            taskPosition.offset(distanceFromMidpoint, 0);
        }
        float distanceToOffscreen = desiredLeft - taskPosition.left;
        // Finally, we need to account for RecentsView scale, because it moves tasks based on its
        // pivot. To do this, we move the task position to where it would be offscreen at scale = 1
        // (computed above), then we apply the scale via getMatrix() to determine how much that
        // moves the task from its desired position, and adjust the computed distance accordingly.
        if (mLastComputedTaskPushOutDistance == null) {
            taskPosition.offsetTo(desiredLeft, 0);
            int midpointScroll = getScrollForPage(midpointIndex);
            getPersistentChildPosition(midpointIndex, midpointScroll, taskPosition);
            float midpointStart = mOrientationHandler.getStart(taskPosition);

            getPersistentChildPosition(childIndex, midpointScroll, taskPosition);
            // Assume child does not overlap with midPointChild.
            isStartShift = mOrientationHandler.getStart(taskPosition) < midpointStart;
        } else {
            // Position the task at scroll position.
            getPersistentChildPosition(childIndex, getScrollForPage(childIndex), taskPosition);
            isStartShift = mIsRtl;
        }

        // Next, calculate the distance to move the task off screen. We also need to account for
        // RecentsView scale, because it moves tasks based on its pivot. To do this, we move the
        // task position to where it would be offscreen at scale = 1 (computed above), then we
        // apply the scale via getMatrix() to determine how much that moves the task from its
        // desired position, and adjust the computed distance accordingly.
        float distanceToOffscreen;
        if (isStartShift) {
            float desiredStart = -mOrientationHandler.getPrimarySize(taskPosition);
            distanceToOffscreen = -mOrientationHandler.getEnd(taskPosition);
            if (mLastComputedTaskStartPushOutDistance == null) {
                taskPosition.offsetTo(
                        mOrientationHandler.getPrimaryValue(desiredStart, 0f),
                        mOrientationHandler.getSecondaryValue(desiredStart, 0f));
                getMatrix().mapRect(taskPosition);
            mLastComputedTaskPushOutDistance = (taskPosition.left - desiredLeft) / getScaleX();
                mLastComputedTaskStartPushOutDistance = mOrientationHandler.getEnd(taskPosition)
                        / mOrientationHandler.getPrimaryScale(this);
            }
            distanceToOffscreen -= mLastComputedTaskStartPushOutDistance;
        } else {
            float desiredStart = mOrientationHandler.getPrimarySize(this);
            distanceToOffscreen = desiredStart - mOrientationHandler.getStart(taskPosition);
            if (mLastComputedTaskEndPushOutDistance == null) {
                taskPosition.offsetTo(
                        mOrientationHandler.getPrimaryValue(desiredStart, 0f),
                        mOrientationHandler.getSecondaryValue(desiredStart, 0f));
                getMatrix().mapRect(taskPosition);
                mLastComputedTaskEndPushOutDistance = (mOrientationHandler.getStart(taskPosition)
                        - desiredStart) / mOrientationHandler.getPrimaryScale(this);
            }
            distanceToOffscreen -= mLastComputedTaskEndPushOutDistance;
        }
        distanceToOffscreen -= mLastComputedTaskPushOutDistance;
        return distanceToOffscreen * offsetProgress;
    }

+24 −9
Original line number Diff line number Diff line
@@ -987,20 +987,30 @@ public class TaskView extends FrameLayout implements Reusable {

    private void applyTranslationX() {
        setTranslationX(mDismissTranslationX + mTaskOffsetTranslationX + mTaskResistanceTranslationX
                + getFullscreenTrans(mFullscreenTranslationX)
                + getNonFullscreenTrans(mNonFullscreenTranslationX)
                + getGridTrans(mGridTranslationX));
                + getPersistentTranslationX());
    }

    private void applyTranslationY() {
        setTranslationY(
                mDismissTranslationY + mTaskOffsetTranslationY + mTaskResistanceTranslationY
                        + getGridTrans(mGridTranslationY) + mBoxTranslationY);
        setTranslationY(mDismissTranslationY + mTaskOffsetTranslationY + mTaskResistanceTranslationY
                + getPersistentTranslationY());
    }

    private float getGridTrans(float endTranslation) {
        float progress = ACCEL_DEACCEL.getInterpolation(mGridProgress);
        return Utilities.mapRange(progress, 0, endTranslation);
    /**
     * Returns addition of translationX that is persistent (e.g. fullscreen and grid), and does not
     * change according to a temporary state (e.g. task offset).
     */
    public float getPersistentTranslationX() {
        return getFullscreenTrans(mFullscreenTranslationX)
                + getNonFullscreenTrans(mNonFullscreenTranslationX)
                + getGridTrans(mGridTranslationX);
    }

    /**
     * Returns addition of translationY that is persistent (e.g. fullscreen and grid), and does not
     * change according to a temporary state (e.g. task offset).
     */
    public float getPersistentTranslationY() {
        return getGridTrans(mGridTranslationY) + mBoxTranslationY;
    }

    public FloatProperty<TaskView> getPrimaryDismissTranslationProperty() {
@@ -1275,6 +1285,11 @@ public class TaskView extends FrameLayout implements Reusable {
        return endTranslation - getFullscreenTrans(endTranslation);
    }

    private float getGridTrans(float endTranslation) {
        float progress = ACCEL_DEACCEL.getInterpolation(mGridProgress);
        return Utilities.mapRange(progress, 0, endTranslation);
    }

    public boolean isRunningTask() {
        if (getRecentsView() == null) {
            return false;
+15 −0
Original line number Diff line number Diff line
@@ -121,11 +121,26 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
        return view.getMeasuredHeight();
    }

    @Override
    public int getPrimarySize(View view) {
        return view.getHeight();
    }

    @Override
    public float getPrimarySize(RectF rect) {
        return rect.height();
    }

    @Override
    public float getStart(RectF rect) {
        return rect.top;
    }

    @Override
    public float getEnd(RectF rect) {
        return rect.bottom;
    }

    @Override
    public int getClearAllSidePadding(View view, boolean isRtl) {
        return (isRtl ? view.getPaddingBottom() : - view.getPaddingTop()) / 2;
+3 −0
Original line number Diff line number Diff line
@@ -65,7 +65,10 @@ public interface PagedOrientationHandler {
    float getPrimaryDirection(MotionEvent event, int pointerIndex);
    float getPrimaryVelocity(VelocityTracker velocityTracker, int pointerId);
    int getMeasuredSize(View view);
    int getPrimarySize(View view);
    float getPrimarySize(RectF rect);
    float getStart(RectF rect);
    float getEnd(RectF rect);
    int getClearAllSidePadding(View view, boolean isRtl);
    int getSecondaryDimension(View view);
    FloatProperty<View> getPrimaryViewTranslate();
+15 −0
Original line number Diff line number Diff line
@@ -117,11 +117,26 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
        return view.getMeasuredWidth();
    }

    @Override
    public int getPrimarySize(View view) {
        return view.getWidth();
    }

    @Override
    public float getPrimarySize(RectF rect) {
        return rect.width();
    }

    @Override
    public float getStart(RectF rect) {
        return rect.left;
    }

    @Override
    public float getEnd(RectF rect) {
        return rect.right;
    }

    @Override
    public int getClearAllSidePadding(View view, boolean isRtl) {
        return (isRtl ? view.getPaddingRight() : - view.getPaddingLeft()) / 2;