Updating the workspace card in recents UI

> Removing the widgets button from the card
> Making the height of the card same as that of the second card
> Using the same swipe rage for going between Normal and Overview state

Change-Id: Ib8bd050c52294bb01522fbcd0236f2221e6fe62d
diff --git a/quickstep/res/layout/overview_panel.xml b/quickstep/res/layout/overview_panel.xml
index 78238fa..9f4f8a1 100644
--- a/quickstep/res/layout/overview_panel.xml
+++ b/quickstep/res/layout/overview_panel.xml
@@ -26,32 +26,6 @@
 
     <com.android.launcher3.uioverrides.WorkspaceCard
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:paddingTop="@dimen/task_thumbnail_top_margin" >
-
-        <View
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:id="@+id/workspace_click_target" />
-
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:id="@+id/widget_button"
-            android:background="@drawable/bg_workspace_card_button" >
-
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/widget_button_text"
-                android:drawableStart="@drawable/ic_widget"
-                android:textColor="?attr/workspaceTextColor"
-                android:drawableTint="?attr/workspaceTextColor"
-                android:gravity="center"
-                android:layout_gravity="center"
-                android:drawablePadding="20dp" />
-        </FrameLayout>
-
-    </com.android.launcher3.uioverrides.WorkspaceCard>
+        android:layout_height="match_parent" />
 
 </com.android.quickstep.RecentsView>
\ No newline at end of file
diff --git a/quickstep/src/com/android/launcher3/uioverrides/EdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/EdgeSwipeController.java
index c1b26d4..356a144 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/EdgeSwipeController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/EdgeSwipeController.java
@@ -29,9 +29,6 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.anim.SpringAnimationHandler;
 import com.android.launcher3.dragndrop.DragLayer;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
 import com.android.launcher3.util.VerticalSwipeController;
 import com.android.quickstep.RecentsView;
 
@@ -40,7 +37,7 @@
  */
 public class EdgeSwipeController extends VerticalSwipeController {
 
-    private final Rect mTempRect = new Rect();
+    private static final Rect sTempRect = new Rect();
 
     public EdgeSwipeController(Launcher l) {
         super(l, NORMAL, OVERVIEW, l.getDeviceProfile().isVerticalBarLayout()
@@ -78,18 +75,22 @@
 
     @Override
     protected float getShiftRange() {
-        RecentsView.getPageRect(mLauncher, mTempRect);
-        DragLayer dl = mLauncher.getDragLayer();
+        return getShiftRange(mLauncher);
+    }
+
+    public static float getShiftRange(Launcher launcher) {
+        RecentsView.getPageRect(launcher.getDeviceProfile(), launcher, sTempRect);
+        DragLayer dl = launcher.getDragLayer();
         Rect insets = dl.getInsets();
 
-        if (mLauncher.getDeviceProfile().isVerticalBarLayout()) {
+        if (launcher.getDeviceProfile().isVerticalBarLayout()) {
             if (insets.left > insets.right) {
-                return insets.left + mTempRect.left;
+                return insets.left + sTempRect.left;
             } else {
-                return dl.getWidth() - mTempRect.right + insets.right;
+                return dl.getWidth() - sTempRect.right + insets.right;
             }
         } else {
-            return dl.getHeight() - mTempRect.bottom + insets.bottom;
+            return dl.getHeight() - sTempRect.bottom + insets.bottom;
         }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 2e5e75e..d2057cf 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -36,8 +36,6 @@
  */
 public class OverviewState extends LauncherState {
 
-    public static final float WORKSPACE_SCALE_ON_SCROLL = 0.9f;
-
     private static final int STATE_FLAGS = FLAG_SHOW_SCRIM | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED;
 
     public OverviewState(int id) {
@@ -47,15 +45,15 @@
     @Override
     public float[] getWorkspaceScaleAndTranslation(Launcher launcher) {
         Rect pageRect = new Rect();
-        RecentsView.getPageRect(launcher, pageRect);
+        RecentsView.getScaledDownPageRect(launcher.getDeviceProfile(), launcher, pageRect);
+        RecentsView rv = launcher.getOverviewPanel();
+
         if (launcher.getWorkspace().getNormalChildWidth() <= 0 || pageRect.isEmpty()) {
             return super.getWorkspaceScaleAndTranslation(launcher);
         }
 
-        RecentsView rv = launcher.getOverviewPanel();
         float overlap = 0;
         if (rv.getCurrentPage() >= rv.getFirstTaskIndex()) {
-            Utilities.scaleRectAboutCenter(pageRect, WORKSPACE_SCALE_ON_SCROLL);
             overlap = launcher.getResources().getDimension(R.dimen.workspace_overview_offset_x);
         }
         return getScaleAndTranslationForPageRect(launcher, overlap, pageRect);
@@ -99,21 +97,23 @@
         float childWidth = ws.getNormalChildWidth();
         float childHeight = ws.getNormalChildHeight();
 
+        float scale = pageRect.height() / childHeight;
         Rect insets = launcher.getDragLayer().getInsets();
-        float scale = Math.min(pageRect.width() / childWidth, pageRect.height() / childHeight);
 
         float halfHeight = ws.getHeight() / 2;
         float childTop = halfHeight - scale * (halfHeight - ws.getPaddingTop() - insets.top);
         float translationY = pageRect.top - childTop;
 
+        // Align the workspace horizontally centered with the task rect
         float halfWidth = ws.getWidth() / 2;
-        float translationX;
+        float childCenter = halfWidth -
+                scale * (halfWidth - ws.getPaddingLeft() - insets.left - childWidth / 2);
+        float translationX = pageRect.exactCenterX() - childCenter;
+
         if (Utilities.isRtl(launcher.getResources())) {
-            float childRight = halfWidth + scale * (halfWidth - ws.getPaddingRight() - insets.right);
-            translationX = childRight - pageRect.right - offsetX / scale;
+            translationX -= offsetX / scale;
         } else {
-            float childLeft = halfWidth - scale * (halfWidth - ws.getPaddingLeft() - insets.left);
-            translationX = pageRect.left - childLeft + offsetX / scale;
+            translationX += offsetX / scale;
         }
 
         return new float[] {scale, translationX, translationY};
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeController.java
index 335077a..1fd541a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeController.java
@@ -29,7 +29,6 @@
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.touch.SwipeDetector;
 import com.android.launcher3.util.TouchController;
@@ -168,7 +167,7 @@
         return mDetector.onTouchEvent(ev);
     }
 
-    private void reinitAnimationController(boolean goingUp) {
+    private void reInitAnimationController(boolean goingUp) {
         if (!goingUp && !mSwipeDownEnabled) {
             goingUp = true;
         }
@@ -191,20 +190,7 @@
             if (goingUp) {
                 mEndDisplacement = -range;
             } else {
-                View ws = mLauncher.getWorkspace();
-                mTempCords[1] = ws.getHeight() - ws.getPaddingBottom();
-                dl.getDescendantCoordRelativeToSelf(ws, mTempCords);
-
-                float distance = mTempCords[1];
-                if (!mLauncher.getDeviceProfile().isVerticalBarLayout()) {
-                    mTempCords[1] = 0;
-                    dl.getDescendantCoordRelativeToSelf(mLauncher.getHotseat(), mTempCords);
-                    distance = mTempCords[1] - distance;
-                } else {
-                    distance = dl.getHeight() - distance;
-                }
-
-                mEndDisplacement = distance;
+                mEndDisplacement = EdgeSwipeController.getShiftRange(mLauncher);
             }
         } else {
             if (goingUp) {
@@ -240,7 +226,7 @@
     @Override
     public void onDragStart(boolean start) {
         if (mCurrentAnimation == null) {
-            reinitAnimationController(mDetector.wasInitialTouchPositive());
+            reInitAnimationController(mDetector.wasInitialTouchPositive());
             mDisplacementShift = 0;
         } else {
             mDisplacementShift = mCurrentAnimation.getProgressFraction() / mProgressMultiplier;
@@ -254,7 +240,7 @@
         boolean isGoingUp =
                 totalDisplacement == 0 ? mCurrentAnimationIsGoingUp : totalDisplacement < 0;
         if (isGoingUp != mCurrentAnimationIsGoingUp) {
-            reinitAnimationController(isGoingUp);
+            reInitAnimationController(isGoingUp);
         }
         mCurrentAnimation.setPlayFraction(totalDisplacement * mProgressMultiplier);
         return true;
@@ -276,7 +262,7 @@
                     // Not allowed
                     goingToEnd = false;
                 } else {
-                    reinitAnimationController(goingUp);
+                    reInitAnimationController(goingUp);
                     goingToEnd = true;
                 }
             } else {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/WorkspaceCard.java b/quickstep/src/com/android/launcher3/uioverrides/WorkspaceCard.java
index 4816e2a..92a09dd 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/WorkspaceCard.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/WorkspaceCard.java
@@ -16,170 +16,80 @@
 package com.android.launcher3.uioverrides;
 
 import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.uioverrides.OverviewState.WORKSPACE_SCALE_ON_SCROLL;
 import static com.android.quickstep.RecentsView.SCROLL_TYPE_WORKSPACE;
 
-import android.animation.FloatArrayEvaluator;
 import android.content.Context;
+import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.widget.FrameLayout;
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
-import com.android.launcher3.widget.WidgetsFullSheet;
 import com.android.quickstep.RecentsView;
 import com.android.quickstep.RecentsView.PageCallbacks;
 import com.android.quickstep.RecentsView.ScrollState;
 
-public class WorkspaceCard extends FrameLayout implements PageCallbacks, OnClickListener {
+public class WorkspaceCard extends View implements PageCallbacks, OnClickListener {
 
     private final Rect mTempRect = new Rect();
-    private final float[] mEvaluatedFloats = new float[3];
-    private final FloatArrayEvaluator mEvaluator = new FloatArrayEvaluator(mEvaluatedFloats);
-
-    // UI related information
-    private float[] mScaleAndTranslatePage0, mScaleAndTranslatePage1;
-    private boolean mUIDataValid = false;
 
     private Launcher mLauncher;
     private Workspace mWorkspace;
 
+    private float mLinearInterpolationForPage2 = 1;
+    private float mTranslateXPage0, mTranslateXPage1;
+    private float mExtraScrollShift;
+
     private boolean mIsWorkspaceScrollingEnabled;
 
-    private View mWorkspaceClickTarget;
-    private View mWidgetsButton;
-
-    private boolean mLayoutHorizontal;
-
     public WorkspaceCard(Context context) {
-        super(context);
+        this(context, null);
     }
 
     public WorkspaceCard(Context context, AttributeSet attrs) {
-        super(context, attrs);
+        this(context, attrs, 0);
     }
 
     public WorkspaceCard(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-
-        mWorkspaceClickTarget = findViewById(R.id.workspace_click_target);
-        mWidgetsButton = findViewById(R.id.widget_button);
-
-        mWorkspaceClickTarget.setOnClickListener(this);
-        mWidgetsButton.setOnClickListener(this);
         setOnClickListener(this);
     }
 
+    /**
+     * Draw nothing.
+     */
     @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        // We measure the dimensions of the PagedView to be larger than the pages so that when we
-        // zoom out (and scale down), the view is still contained in the parent
-        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
-        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
-        if (widthMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.UNSPECIFIED) {
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-            return;
-        }
-
-        // Return early if we aren't given a proper dimension
-        if (widthSize <= 0 || heightSize <= 0) {
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-            return;
-        }
-
-        float workspaceWidth = mWorkspace.getNormalChildWidth();
-        float workspaceHeight = mWorkspace.getNormalChildHeight();
-
-        int availableWidth = widthSize - getPaddingLeft() - getPaddingRight();
-        float scaleX = availableWidth / workspaceWidth;
-
-        int availableHeight = heightSize - getPaddingTop() - getPaddingBottom();
-        float scaleY = availableHeight / workspaceHeight;
-
-        if (scaleX < scaleY) {
-            mLayoutHorizontal = false;
-            int childWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.EXACTLY);
-
-            int pageHeight = Math.round(workspaceHeight * scaleX);
-            mWorkspaceClickTarget.measure(childWidthSpec,
-                    MeasureSpec.makeMeasureSpec(pageHeight, MeasureSpec.EXACTLY));
-
-            int buttonHeight = availableHeight - pageHeight;
-            mWidgetsButton.measure(childWidthSpec,
-                    MeasureSpec.makeMeasureSpec(buttonHeight, MeasureSpec.EXACTLY));
-        } else {
-            mLayoutHorizontal = true;
-            int childHeightSpec = MeasureSpec.makeMeasureSpec(availableHeight, MeasureSpec.EXACTLY);
-
-            int pageWidth = Math.round(workspaceWidth * scaleY);
-            mWorkspaceClickTarget.measure(
-                    MeasureSpec.makeMeasureSpec(pageWidth, MeasureSpec.EXACTLY), childHeightSpec);
-
-            int buttonWidth = availableWidth - pageWidth;
-            mWidgetsButton.measure(
-                    MeasureSpec.makeMeasureSpec(buttonWidth, MeasureSpec.EXACTLY), childHeightSpec);
-        }
-        setMeasuredDimension(widthSize, heightSize);
-    }
+    public void draw(Canvas canvas) { }
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        int x = getPaddingLeft();
-        int y = getPaddingTop();
+        super.onLayout(changed, left, top, right, bottom);
 
-        if (mLayoutHorizontal) {
-            final View first, second;
-            if (Utilities.isRtl(getResources())) {
-                first = mWidgetsButton;
-                second = mWorkspaceClickTarget;
-            } else {
-                first = mWorkspaceClickTarget;
-                second = mWidgetsButton;
-            }
-            int x2 = x + first.getMeasuredWidth();
-            first.layout(x, y,
-                    x2, y + first.getMeasuredHeight());
-            second.layout(x2, y,
-                    x2 + second.getMeasuredWidth(),
-                    y + second.getMeasuredHeight());
-        } else {
-            int y2 = y + mWorkspaceClickTarget.getMeasuredHeight();
-            mWorkspaceClickTarget.layout(x, y,
-                    x + mWorkspaceClickTarget.getMeasuredWidth(), y2);
-            mWidgetsButton.layout(x, y2,
-                    x + mWidgetsButton.getMeasuredWidth(),
-                    y2 + mWidgetsButton.getMeasuredHeight());
+        // Initiate data
+        mLinearInterpolationForPage2 = RecentsView.getScaledDownPageRect(
+                mLauncher.getDeviceProfile(), mLauncher, mTempRect);
+
+        float[] scale = OverviewState.getScaleAndTranslationForPageRect(mLauncher, 0, mTempRect);
+        mTranslateXPage0 = scale[1];
+        mTranslateXPage1 = OverviewState
+                .getScaleAndTranslationForPageRect(mLauncher,
+                        getResources().getDimension(R.dimen.workspace_overview_offset_x),
+                        mTempRect)[1];
+
+        mExtraScrollShift = 0;
+        if (mWorkspace != null && getWidth() > 0) {
+            float workspaceWidth = mWorkspace.getNormalChildWidth() * scale[0];
+            mExtraScrollShift = (workspaceWidth - getWidth()) / 2;
+            setScaleX(workspaceWidth / getWidth());
         }
-
-        mUIDataValid = false;
     }
 
     @Override
     public void onClick(View view) {
-        if (view == mWorkspaceClickTarget || view == this) {
-            mLauncher.getStateManager().goToState(NORMAL);
-        } else if (view == mWidgetsButton) {
-            WidgetsFullSheet.show(mLauncher, true);
-        }
-    }
-
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        super.onSizeChanged(w, h, oldw, oldh);
-        mUIDataValid = false;
+        mLauncher.getStateManager().goToState(NORMAL);
     }
 
     public void setup(Launcher launcher) {
@@ -194,41 +104,24 @@
     @Override
     public int onPageScroll(ScrollState scrollState) {
         float factor = scrollState.linearInterpolation;
-        float scale = factor * WORKSPACE_SCALE_ON_SCROLL + (1 - factor);
-        setScaleX(scale);
-        setScaleY(scale);
-
         float translateX = scrollState.distanceFromScreenCenter;
         if (mIsWorkspaceScrollingEnabled) {
-            initUiData();
-
-            mEvaluator.evaluate(factor, mScaleAndTranslatePage0, mScaleAndTranslatePage1);
-            mWorkspace.setScaleX(mEvaluatedFloats[0]);
-            mWorkspace.setScaleY(mEvaluatedFloats[0]);
-            mWorkspace.setTranslationX(mEvaluatedFloats[1]);
-            mWorkspace.setTranslationY(mEvaluatedFloats[2]);
-            translateX += mEvaluatedFloats[1] - mScaleAndTranslatePage0[1];
+            float shift = factor * (mTranslateXPage1 - mTranslateXPage0);
+            mWorkspace.setTranslationX(shift + mTranslateXPage0);
+            translateX += shift;
         }
 
         setTranslationX(translateX);
 
-        return SCROLL_TYPE_WORKSPACE;
-    }
-
-    private void initUiData() {
-        if (mUIDataValid && mScaleAndTranslatePage0 != null) {
-            return;
+        // If the workspace card is still the first page, shift all the other pages.
+        if (scrollState.linearInterpolation > mLinearInterpolationForPage2) {
+            scrollState.prevPageExtraWidth = 0;
+        } else if (mLinearInterpolationForPage2 > 0) {
+            scrollState.prevPageExtraWidth = mExtraScrollShift *
+                    (1 - scrollState.linearInterpolation / mLinearInterpolationForPage2);
+        } else {
+            scrollState.prevPageExtraWidth = mExtraScrollShift;
         }
-
-        float overlap = getResources().getDimension(R.dimen.workspace_overview_offset_x);
-
-        RecentsView.getPageRect(mLauncher, mTempRect);
-        mScaleAndTranslatePage0 = OverviewState
-                .getScaleAndTranslationForPageRect(mLauncher, 0, mTempRect);
-        Rect scaledDown = new Rect(mTempRect);
-        Utilities.scaleRectAboutCenter(scaledDown, WORKSPACE_SCALE_ON_SCROLL);
-        mScaleAndTranslatePage1 = OverviewState
-                .getScaleAndTranslationForPageRect(mLauncher, overlap, scaledDown);
-        mUIDataValid = true;
+        return SCROLL_TYPE_WORKSPACE;
     }
 }
diff --git a/quickstep/src/com/android/quickstep/RecentsView.java b/quickstep/src/com/android/quickstep/RecentsView.java
index d1bbd23..9c757bf 100644
--- a/quickstep/src/com/android/quickstep/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/RecentsView.java
@@ -27,6 +27,7 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.PagedView;
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.uioverrides.OverviewState;
 import com.android.launcher3.uioverrides.RecentsViewStateController;
 import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
@@ -41,12 +42,16 @@
 import java.util.ArrayList;
 
 import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.quickstep.TaskView.CURVE_FACTOR;
+import static com.android.quickstep.TaskView.CURVE_INTERPOLATOR;
 
 /**
  * A list of recent tasks.
  */
 public class RecentsView extends PagedView {
 
+    private static final Rect sTempStableInsets = new Rect();
+
     public static final int SCROLL_TYPE_NONE = 0;
     public static final int SCROLL_TYPE_TASK = 1;
     public static final int SCROLL_TYPE_WORKSPACE = 2;
@@ -219,19 +224,18 @@
     }
 
     private static Rect getPadding(DeviceProfile profile, Context context) {
-        Rect stableInsets = new Rect();
-        WindowManagerWrapper.getInstance().getStableInsets(stableInsets);
+        WindowManagerWrapper.getInstance().getStableInsets(sTempStableInsets);
         Rect padding = new Rect(profile.workspacePadding);
 
-        float taskWidth = profile.widthPx - stableInsets.left - stableInsets.right;
-        float taskHeight = profile.heightPx - stableInsets.top - stableInsets.bottom;
+        float taskWidth = profile.widthPx - sTempStableInsets.left - sTempStableInsets.right;
+        float taskHeight = profile.heightPx - sTempStableInsets.top - sTempStableInsets.bottom;
 
         float overviewHeight, overviewWidth;
         if (profile.isVerticalBarLayout()) {
             // Use the same padding on both sides for symmetry.
             float availableWidth = taskWidth - 2 * Math.max(padding.left, padding.right);
             float availableHeight = profile.availableHeightPx - padding.top - padding.bottom
-                    - stableInsets.top
+                    - sTempStableInsets.top
                     - profile.heightPx * (1 - OverviewState.getVerticalProgress(profile, context));
 
             float scaledRatio = Math.min(availableWidth / taskWidth, availableHeight / taskHeight);
@@ -240,18 +244,41 @@
 
         } else {
             overviewHeight = profile.availableHeightPx - padding.top - padding.bottom
-                    - stableInsets.top;
+                    - sTempStableInsets.top;
             overviewWidth = taskWidth * overviewHeight / taskHeight;
         }
 
-        padding.bottom = profile.availableHeightPx - padding.top - stableInsets.top
+        padding.bottom = profile.availableHeightPx - padding.top - sTempStableInsets.top
                 - Math.round(overviewHeight);
         padding.left = padding.right = (int) ((profile.availableWidthPx - overviewWidth) / 2);
         return padding;
     }
 
-    public static void getPageRect(Launcher launcher, Rect outRect) {
-        getPageRect(launcher.getDeviceProfile(), launcher, outRect);
+    /**
+     * Sets the {@param outRect} to match the position of the first tile such that it is scaled
+     * down to match the 2nd taskView.
+     * @return returns the factor which determines the scaling factor for the second task.
+     */
+    public static float getScaledDownPageRect(DeviceProfile dp, Context context, Rect outRect) {
+        getPageRect(dp, context, outRect);
+
+        int pageSpacing = context.getResources()
+                .getDimensionPixelSize(R.dimen.recents_page_spacing);
+        float halfScreenWidth = dp.widthPx * 0.5f;
+        float halfPageWidth = outRect.width() * 0.5f;
+        float pageCenter = outRect.right + pageSpacing + halfPageWidth;
+        float distanceFromCenter = Math.abs(halfScreenWidth - pageCenter);
+        float distanceToReachEdge = halfScreenWidth + halfPageWidth + pageSpacing;
+        float linearInterpolation = Math.min(1, distanceFromCenter / distanceToReachEdge);
+
+        float scale = 1 - CURVE_INTERPOLATOR.getInterpolation(linearInterpolation) * CURVE_FACTOR;
+
+        int topMargin = context.getResources()
+                .getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
+        outRect.top -= topMargin;
+        Utilities.scaleRectAboutCenter(outRect, scale);
+        outRect.top += (int) (scale * topMargin);
+        return linearInterpolation;
     }
 
     public static void getPageRect(DeviceProfile grid, Context context, Rect outRect) {
@@ -393,5 +420,7 @@
         public int halfPageWidth;
         public float distanceFromScreenCenter;
         public float linearInterpolation;
+
+        public float prevPageExtraWidth;
     }
 }
diff --git a/quickstep/src/com/android/quickstep/TaskView.java b/quickstep/src/com/android/quickstep/TaskView.java
index 3f733ca..5c15a76 100644
--- a/quickstep/src/com/android/quickstep/TaskView.java
+++ b/quickstep/src/com/android/quickstep/TaskView.java
@@ -49,9 +49,9 @@
 public class TaskView extends FrameLayout implements TaskCallbacks, PageCallbacks {
 
     /** Designates how "curvy" the carousel is from 0 to 1, where 0 is a straight line. */
-    private static final float CURVE_FACTOR = 0.25f;
+    public static final float CURVE_FACTOR = 0.25f;
     /** A circular curve of x from 0 to 1, where 0 is the center of the screen and 1 is the edge. */
-    private static final TimeInterpolator CURVE_INTERPOLATOR
+    public static final TimeInterpolator CURVE_INTERPOLATOR
             = x -> (float) (1 - Math.sqrt(1 - Math.pow(x, 2)));
 
     /**
@@ -206,13 +206,14 @@
             // Make sure that the task cards do not overlap with the workspace card
             float min = scrollState.halfPageWidth * (1 - scale);
             if (scrollState.isRtl) {
-                setTranslationX(Math.min(translation, min));
+                setTranslationX(Math.min(translation, min) - scrollState.prevPageExtraWidth);
             } else {
-                setTranslationX(Math.max(translation, -min));
+                setTranslationX(Math.max(translation, -min) + scrollState.prevPageExtraWidth);
             }
         } else {
             setTranslationX(translation);
         }
+        scrollState.prevPageExtraWidth = 0;
         return SCROLL_TYPE_TASK;
     }
 }