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

Commit 3e81d090 authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Updating layouts to use frame vs translation and clipping."

parents 752b070e bb410951
Loading
Loading
Loading
Loading
+0 −26
Original line number Diff line number Diff line
@@ -46,19 +46,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
                }
            };

    public static final Property<AnimateableViewBounds, Integer> CLIP_RIGHT =
            new IntProperty<AnimateableViewBounds>("clipRight") {
                @Override
                public void setValue(AnimateableViewBounds object, int clip) {
                    object.setClipRight(clip, false /* force */);
                }

                @Override
                public Integer get(AnimateableViewBounds object) {
                    return object.getClipRight();
                }
            };

    public AnimateableViewBounds(View source, int cornerRadius) {
        mSourceView = source;
        mCornerRadius = cornerRadius;
@@ -102,19 +89,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
        return mClipRect.bottom;
    }

    /** Sets the right clip. */
    public void setClipRight(int right, boolean force) {
        if (right != mClipRect.right || force) {
            mClipRect.right = right;
            updateClipBounds();
        }
    }

    /** Returns the right clip. */
    public int getClipRight() {
        return mClipRect.right;
    }

    private void updateClipBounds() {
        mClipBounds.set(mClipRect.left, mClipRect.top,
                mSourceView.getWidth() - mClipRect.right,
+24 −29
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.systemui.recents.views;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;

import java.util.Collections;
@@ -80,7 +79,6 @@ public class FreeformWorkspaceLayoutAlgorithm {
                float width = normalizedTaskWidths[i] * rowScale;
                if (rowWidth + width > normalizedWorkspaceWidth) {
                    // That is too long for this row, create new row
                    rowWidth = 0f;
                    if ((rowCount + 1) * rowScale > normalizedWorkspaceHeight) {
                        // The new row is too high, so we need to try fitting again.  Update the
                        // scale to be the smaller of the scale needed to fit the task in the
@@ -88,9 +86,11 @@ public class FreeformWorkspaceLayoutAlgorithm {
                        rowScale = Math.min(normalizedWorkspaceWidth / (rowWidth + width),
                                normalizedWorkspaceHeight / (rowCount + 1));
                        rowCount = 1;
                        rowWidth = 0;
                        i = 0;
                    } else {
                        // The new row fits, so continue
                        rowWidth = width;
                        rowCount++;
                        i++;
                    }
@@ -103,20 +103,20 @@ public class FreeformWorkspaceLayoutAlgorithm {
            }

            // Normalize each of the actual rects to that scale
            int height = (int) (rowScale * workspaceHeight);
            float rowTop = ((1f - (rowScale * rowCount)) * workspaceHeight) / 2f;
            float defaultRowLeft = ((1f - (maxRowWidth / normalizedWorkspaceWidth)) *
                    workspaceWidth) / 2f;
            float rowLeft = defaultRowLeft;
            float rowTop = ((1f - (rowScale * rowCount)) * workspaceHeight) / 2f;
            float rowHeight = rowScale * workspaceHeight;
            for (int i = 0; i < numFreeformTasks; i++) {
                Task task = freeformTasks.get(i);
                int width = (int) (height * normalizedTaskWidths[i]);
                float width = rowHeight * normalizedTaskWidths[i];
                if (rowLeft + width > workspaceWidth) {
                    // This goes on the next line
                    rowTop += height;
                    rowTop += rowHeight;
                    rowLeft = defaultRowLeft;
                }
                RectF rect = new RectF(rowLeft, rowTop, rowLeft + width, rowTop + height);
                RectF rect = new RectF(rowLeft, rowTop, rowLeft + width, rowTop + rowHeight);
                rowLeft += width;
                mTaskRectMap.put(task.key, rect);
            }
@@ -140,34 +140,29 @@ public class FreeformWorkspaceLayoutAlgorithm {
    public TaskViewTransform getTransform(Task task, TaskViewTransform transformOut,
            TaskStackLayoutAlgorithm stackLayout) {
        if (mTaskRectMap.containsKey(task.key)) {
            Rect taskRect = stackLayout.mTaskRect;
            RectF ffRect = mTaskRectMap.get(task.key);
            float scale = Math.max(ffRect.width() / taskRect.width(),
                    ffRect.height() / taskRect.height());
            int topOffset = (stackLayout.mFreeformRect.top - taskRect.top);
            int scaleXOffset = (int) (((1f - scale) * taskRect.width()) / 2);
            int scaleYOffset = (int) (((1f - scale) * taskRect.height()) / 2);
            final Rect taskRect = stackLayout.mTaskRect;
            final RectF ffRect = mTaskRectMap.get(task.key);

            transformOut.scale = scale * 0.95f;
            transformOut.translationX = (int) (ffRect.left - scaleXOffset);
            transformOut.translationY = (int) (topOffset + ffRect.top - scaleYOffset);
            transformOut.scale = 0.95f;
            transformOut.alpha = 1f;
            transformOut.translationZ = stackLayout.mMaxTranslationZ;
            transformOut.clipBottom = (int) (taskRect.height() - (ffRect.height() / scale));
            transformOut.clipRight = (int) (taskRect.width() - (ffRect.width() / scale));
            if (task.thumbnail != null) {
                if (task.bounds == null) {
                    // This is a stack task that has no freeform thumbnail, so keep the same bitmap
                    // scale as it had in the stack
                    transformOut.thumbnailScale = (float) taskRect.width() /
                            task.thumbnail.getWidth();
                } else {
                    // This is a freeform rect so fit the bitmap to the task bounds
                    transformOut.thumbnailScale = Math.min(
                        ((float) taskRect.width() - transformOut.clipRight) /
                                task.thumbnail.getWidth(),
                        ((float) taskRect.height() - transformOut.clipBottom) /
                                task.thumbnail.getHeight());
                            ffRect.width() / task.thumbnail.getWidth(),
                            ffRect.height() / task.thumbnail.getHeight());
                }
            } else {
                transformOut.thumbnailScale = 1f;
            }
            transformOut.rect.set(taskRect);
            transformOut.rect.offset(transformOut.translationX, transformOut.translationY);
            Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
            transformOut.rect.right -= transformOut.clipRight * scale;
            transformOut.rect.bottom -= transformOut.clipBottom * scale;
            transformOut.rect.set(ffRect);
            transformOut.rect.offset(stackLayout.mFreeformRect.left, stackLayout.mFreeformRect.top);
            transformOut.visible = true;
            transformOut.p = 1f;

+12 −5
Original line number Diff line number Diff line
@@ -506,6 +506,15 @@ public class TaskStackLayoutAlgorithm {
        return 0f;
    }

    /**
     * Returns the task progress that would put the task just off the back of the stack.
     */
    public float getStackBackTaskProgress(float stackScroll) {
        float min = mUnfocusedRange.relativeMin +
                mFocusState * (mFocusedRange.relativeMin - mUnfocusedRange.relativeMin);
        return stackScroll + min;
    }

    /**
     * Returns the task progress that would put the task just off the front of the stack.
     */
@@ -647,6 +656,7 @@ public class TaskStackLayoutAlgorithm {
            return transformOut;
        }

        int x = (mStackRect.width() - mTaskRect.width()) / 2;
        int y;
        float z;
        float relP;
@@ -671,16 +681,13 @@ public class TaskStackLayoutAlgorithm {

        // Fill out the transform
        transformOut.scale = 1f;
        transformOut.translationX = (mStackRect.width() - mTaskRect.width()) / 2;
        transformOut.translationY = y;
        transformOut.alpha = 1f;
        transformOut.translationZ = z;
        transformOut.rect.set(mTaskRect);
        transformOut.rect.offset(transformOut.translationX, transformOut.translationY);
        transformOut.rect.offset(x, y);
        Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
        transformOut.visible = (transformOut.rect.top < mStackRect.bottom) &&
                (frontTransform == null || transformOut.rect.top != frontTransform.rect.top);
        transformOut.clipBottom = 0;
        transformOut.clipRight = 0;
        transformOut.thumbnailScale = 1f;
        transformOut.p = relP;
        return transformOut;
+29 −23
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -126,6 +127,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
    Task mFocusedTask;
    // Optimizations
    int mStackViewsAnimationDuration;
    int mTaskCornerRadiusPx;
    boolean mStackViewsDirty = true;
    boolean mStackViewsClipDirty = true;
    boolean mAwaitingFirstLayout = true;
@@ -174,6 +176,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal

    public TaskStackView(Context context, TaskStack stack) {
        super(context);
        Resources res = context.getResources();

        // Set the stack first
        setStack(stack);
        mViewPool = new ViewPool<>(context, this);
@@ -184,6 +188,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
        mTouchHandler = new TaskStackViewTouchHandler(context, this, mStackScroller);
        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
                com.android.internal.R.interpolator.fast_out_slow_in);
        mTaskCornerRadiusPx = res.getDimensionPixelSize(
                R.dimen.recents_task_view_rounded_corners_radius);

        int taskBarDismissDozeDelaySeconds = getResources().getInteger(
                R.integer.recents_task_bar_dismiss_delay_seconds);
@@ -364,8 +370,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
    private boolean updateStackTransforms(ArrayList<TaskViewTransform> taskTransforms,
                                       ArrayList<Task> tasks,
                                       float stackScroll,
                                       int[] visibleRangeOut,
                                       boolean boundTranslationsToRect) {
                                       int[] visibleRangeOut) {
        int taskTransformCount = taskTransforms.size();
        int taskCount = tasks.size();
        int frontMostVisibleIndex = -1;
@@ -411,11 +416,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
                    break;
                }
            }

            if (boundTranslationsToRect) {
                transform.translationY = Math.min(transform.translationY,
                        mLayoutAlgorithm.mStackRect.bottom);
            }
            frontTransform = transform;
        }
        if (visibleRangeOut != null) {
@@ -433,7 +433,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
            float stackScroll = mStackScroller.getStackScroll();
            int[] visibleStackRange = mTmpVisibleRange;
            boolean isValidVisibleStackRange = updateStackTransforms(mCurrentTaskTransforms, tasks,
                    stackScroll, visibleStackRange, false);
                    stackScroll, visibleStackRange);
            boolean hasStackBackTransform = false;
            boolean hasStackFrontTransform = false;
            if (DEBUG) {
@@ -490,7 +490,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
                }

                // Animate the task into place
                tv.updateViewPropertiesToTaskTransform(transform, transform.clipBottom,
                tv.updateViewPropertiesToTaskTransform(transform, 0,
                        mStackViewsAnimationDuration, mFastOutSlowInInterpolator,
                        mRequestUpdateClippingListener);

@@ -513,8 +513,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
                        if (Float.compare(transform.p, 0f) <= 0) {
                            if (!hasStackBackTransform) {
                                hasStackBackTransform = true;
                                mLayoutAlgorithm.getStackTransform(0f, 0f, mTmpStackBackTransform,
                                        null);
                                mLayoutAlgorithm.getStackTransform(
                                        mLayoutAlgorithm.getStackBackTaskProgress(0f), 0f,
                                        mTmpStackBackTransform, null);
                            }
                            tv.updateViewPropertiesToTaskTransform(mTmpStackBackTransform, 0, 0,
                                    mFastOutSlowInInterpolator, mRequestUpdateClippingListener);
@@ -586,17 +587,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
                // stacked and we can make assumptions about the visibility of the this
                // task relative to the ones in front of it.
                if (frontTv != null) {
                    mTmpTaskRect.set(mLayoutAlgorithm.mTaskRect);
                    mTmpTaskRect.offset(0, tv.getTranslationY());
                    Utilities.scaleRectAboutCenter(mTmpTaskRect, tv.getScaleX());
                    float taskBottom = mTmpTaskRect.bottom;
                    mTmpTaskRect.set(mLayoutAlgorithm.mTaskRect);
                    mTmpTaskRect.offset(0, frontTv.getTranslationY());
                    Utilities.scaleRectAboutCenter(mTmpTaskRect, frontTv.getScaleX());
                    float frontTaskTop = mTmpTaskRect.top;
                    float taskBottom = tv.getBottom();
                    float frontTaskTop = frontTv.getTop();
                    if (frontTaskTop < taskBottom) {
                        // Map the stack view space coordinate (the rects) to view space
                        clipBottom = (int) ((taskBottom - frontTaskTop) / tv.getScaleX()) - 1;
                        clipBottom = (int) (taskBottom - frontTaskTop) - mTaskCornerRadiusPx;
                    }
                }
            }
@@ -980,11 +975,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
            onFirstLayout();
        }

        requestSynchronizeStackViewsWithModel();
        if (changed) {
            if (mStackScroller.isScrollOutOfBounds()) {
                mStackScroller.boundScroll();
            }
            requestSynchronizeStackViewsWithModel();
            synchronizeStackViewsWithModel();
            requestUpdateStackViewsClip();
            clipTaskViews(true /* forceUpdate */);
@@ -1147,8 +1142,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
        transformPointToViewLocal(point, tv);
        x = point[0];
        y = point[1];
        return (0 <= x) && (x < (tv.getMeasuredWidth() - tv.getViewBounds().getClipRight())) &&
                (0 <= y) && (y < (tv.getMeasuredHeight() - tv.getViewBounds().getClipBottom()));
        return (0 <= x) && (x < tv.getWidth()) && (0 <= y) && (y < tv.getHeight());
    }

    @Override
@@ -1498,6 +1492,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
        event.taskView.animate()
                .withEndAction(event.postAnimationTrigger.decrementAsRunnable());

        // We translated the view but we need to animate it back from the current layout-space rect
        // to its final layout-space rect
        int x = (int) event.taskView.getTranslationX();
        int y = (int) event.taskView.getTranslationY();
        Rect taskViewRect = new Rect(event.taskView.getLeft(), event.taskView.getTop(),
                event.taskView.getRight(), event.taskView.getBottom());
        taskViewRect.offset(x, y);
        event.taskView.setTranslationX(0);
        event.taskView.setTranslationY(0);
        event.taskView.setLeftTopRightBottom(taskViewRect.left, taskViewRect.top,
                taskViewRect.right, taskViewRect.bottom);

        // Animate the tack view back into position
        requestSynchronizeStackViewsWithModel(250);
    }
+13 −6
Original line number Diff line number Diff line
@@ -232,8 +232,14 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
            mClipAnimation.playTogether(
                    ObjectAnimator.ofInt(mViewBounds, AnimateableViewBounds.CLIP_BOTTOM,
                            mViewBounds.getClipBottom(), clipBottom),
                    ObjectAnimator.ofInt(mViewBounds, AnimateableViewBounds.CLIP_RIGHT,
                            mViewBounds.getClipRight(), toTransform.clipRight),
                    ObjectAnimator.ofInt(this, TaskViewTransform.LEFT, getLeft(),
                            (int) toTransform.rect.left),
                    ObjectAnimator.ofInt(this, TaskViewTransform.TOP, getTop(),
                            (int) toTransform.rect.top),
                    ObjectAnimator.ofInt(this, TaskViewTransform.RIGHT, getRight(),
                            (int) toTransform.rect.right),
                    ObjectAnimator.ofInt(this, TaskViewTransform.BOTTOM, getBottom(),
                            (int) toTransform.rect.bottom),
                    ObjectAnimator.ofFloat(mThumbnailView, TaskViewThumbnail.BITMAP_SCALE,
                            mThumbnailView.getBitmapScale(), toTransform.thumbnailScale));
            mClipAnimation.setStartDelay(toTransform.startDelay);
@@ -242,8 +248,9 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
            mClipAnimation.start();
        } else {
            mViewBounds.setClipBottom(clipBottom, false /* forceUpdate */);
            mViewBounds.setClipRight(toTransform.clipRight, false /* forceUpdate */);
            mThumbnailView.setBitmapScale(toTransform.thumbnailScale);
            setLeftTopRightBottom((int) toTransform.rect.left, (int) toTransform.rect.top,
                    (int) toTransform.rect.right, (int) toTransform.rect.bottom);
        }
        if (!config.useHardwareLayers) {
            mThumbnailView.updateThumbnailVisibility(clipBottom - getPaddingBottom());
@@ -336,10 +343,10 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
            } else {
                // Animate the task up if it was occluding the launch target
                if (ctx.currentTaskOccludesLaunchTarget) {
                    setTranslationY(transform.translationY + taskViewAffiliateGroupEnterOffset);
                    setTranslationY(taskViewAffiliateGroupEnterOffset);
                    setAlpha(0f);
                    animate().alpha(1f)
                            .translationY(transform.translationY)
                            .translationY(0)
                            .setUpdateListener(null)
                            .setListener(new AnimatorListenerAdapter() {
                                private boolean hasEnded;
@@ -372,7 +379,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
                animate().translationZ(transform.translationZ);
            }
            animate()
                    .translationY(transform.translationY)
                    .translationY(0)
                    .setStartDelay(delay)
                    .setUpdateListener(ctx.updateListener)
                    .setListener(new AnimatorListenerAdapter() {
Loading