Merge "Small optimizations for the All Apps transition"
diff --git a/src/com/android/launcher2/DeleteDropTarget.java b/src/com/android/launcher2/DeleteDropTarget.java
index f199708..3b82f9e 100644
--- a/src/com/android/launcher2/DeleteDropTarget.java
+++ b/src/com/android/launcher2/DeleteDropTarget.java
@@ -193,7 +193,7 @@
         };
         dragLayer.animateView(d.dragView, from, to, 0.1f, 0.1f,
                 DELETE_ANIMATION_DURATION, new DecelerateInterpolator(2),
-                new DecelerateInterpolator(1.5f), onAnimationEndRunnable, false);
+                new DecelerateInterpolator(1.5f), onAnimationEndRunnable, false, null);
     }
 
     private void completeDrop(DragObject d) {
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index 9154771..c315b60 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -63,6 +63,8 @@
     private ValueAnimator mFadeOutAnim = null;
     private TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
     private View mDropView = null;
+    private int mAnchorViewInitialScrollX = 0;
+    private View mAnchorView = null;
 
     private int[] mDropViewPos = new int[2];
     private float mDropViewScale;
@@ -420,16 +422,16 @@
         final int fromY = r.top;
 
         animateViewIntoPosition(dragView, fromX, fromY, pos[0], pos[1], scale,
-                onFinishRunnable, true, -1);
+                onFinishRunnable, true, -1, null);
     }
 
     public void animateViewIntoPosition(DragView dragView, final View child,
             final Runnable onFinishAnimationRunnable) {
-        animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable);
+        animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, null);
     }
 
     public void animateViewIntoPosition(DragView dragView, final View child, int duration,
-            final Runnable onFinishAnimationRunnable) {
+            final Runnable onFinishAnimationRunnable, View anchorView) {
         ((CellLayoutChildren) child.getParent()).measureChild(child);
         CellLayout.LayoutParams lp =  (CellLayout.LayoutParams) child.getLayoutParams();
 
@@ -485,16 +487,17 @@
             }
         };
         animateViewIntoPosition(dragView, fromX, fromY, toX, toY, scale,
-                onCompleteRunnable, true, duration);
+                onCompleteRunnable, true, duration, anchorView);
     }
 
     private void animateViewIntoPosition(final View view, final int fromX, final int fromY,
             final int toX, final int toY, float finalScale, Runnable onCompleteRunnable,
-            boolean fadeOut, int duration) {
+            boolean fadeOut, int duration, View anchorView) {
         Rect from = new Rect(fromX, fromY, fromX +
                 view.getMeasuredWidth(), fromY + view.getMeasuredHeight());
         Rect to = new Rect(toX, toY, toX + view.getMeasuredWidth(), toY + view.getMeasuredHeight());
-        animateView(view, from, to, 1f, finalScale, duration, null, null, onCompleteRunnable, true);
+        animateView(view, from, to, 1f, finalScale, duration, null, null,
+                onCompleteRunnable, true, anchorView);
     }
 
     /**
@@ -514,11 +517,14 @@
      * @param onCompleteRunnable Optional runnable to run on animation completion.
      * @param fadeOut Whether or not to fade out the view once the animation completes. If true,
      *        the runnable will execute after the view is faded out.
+     * @param anchorView If not null, this represents the view which the animated view stays
+     *        anchored to in case scrolling is currently taking place. Note: currently this is
+     *        only used for the X dimension for the case of the workspace.
      */
     public void animateView(final View view, final Rect from, final Rect to, final float finalAlpha,
             final float finalScale, int duration, final Interpolator motionInterpolator,
             final Interpolator alphaInterpolator, final Runnable onCompleteRunnable,
-            final boolean fadeOut) {
+            final boolean fadeOut, View anchorView) {
         // Calculate the duration of the animation based on the object's distance
         final float dist = (float) Math.sqrt(Math.pow(to.left - from.left, 2) +
                 Math.pow(to.top - from.top, 2));
@@ -548,6 +554,11 @@
             mDropAnim.setInterpolator(mCubicEaseOutInterpolator);
         }
 
+        if (anchorView != null) {
+            mAnchorViewInitialScrollX = anchorView.getScrollX();
+        }
+        mAnchorView = anchorView;
+
         mDropAnim.setDuration(duration);
         mDropAnim.setFloatValues(0.0f, 1.0f);
         mDropAnim.removeAllUpdateListeners();
@@ -662,7 +673,8 @@
             // We are animating an item that was just dropped on the home screen.
             // Render its View in the current animation position.
             canvas.save(Canvas.MATRIX_SAVE_FLAG);
-            final int xPos = mDropViewPos[0] - mDropView.getScrollX();
+            final int xPos = mDropViewPos[0] - mDropView.getScrollX() + (mAnchorView != null
+                    ? (mAnchorViewInitialScrollX - mAnchorView.getScrollX()) : 0);
             final int yPos = mDropViewPos[1] - mDropView.getScrollY();
             int width = mDropView.getMeasuredWidth();
             int height = mDropView.getMeasuredHeight();
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index fdde4d5..f5bd7db 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -74,18 +74,13 @@
     private final LayoutInflater mInflater;
     private final IconCache mIconCache;
     private int mState = STATE_NONE;
-    private static final int FULL_GROW = 0;
-    private static final int PARTIAL_GROW = 1;
     private static final int REORDER_ANIMATION_DURATION = 230;
     private static final int ON_EXIT_CLOSE_DELAY = 800;
-    private int mMode = PARTIAL_GROW;
     private boolean mRearrangeOnClose = false;
     private FolderIcon mFolderIcon;
     private int mMaxCountX;
     private int mMaxCountY;
     private int mMaxNumItems;
-    private Rect mNewSize = new Rect();
-    private Rect mIconRect = new Rect();
     private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
     private Drawable mIconDrawable;
     boolean mItemsInvalidated = false;
@@ -365,21 +360,9 @@
      */
     private void positionAndSizeAsIcon() {
         if (!(getParent() instanceof DragLayer)) return;
-
-        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
-
-        if (mMode == PARTIAL_GROW) {
-            setScaleX(0.8f);
-            setScaleY(0.8f);
-            setAlpha(0f);
-        } else {
-            mLauncher.getDragLayer().getDescendantRectRelativeToSelf(mFolderIcon, mIconRect);
-            lp.width = mIconRect.width();
-            lp.height = mIconRect.height();
-            lp.x = mIconRect.left;
-            lp.y = mIconRect.top;
-            mContent.setAlpha(0);
-        }
+        setScaleX(0.8f);
+        setScaleY(0.8f);
+        setAlpha(0f);
         mState = STATE_SMALL;
     }
 
@@ -387,34 +370,11 @@
         positionAndSizeAsIcon();
 
         if (!(getParent() instanceof DragLayer)) return;
-
-        ObjectAnimator oa;
-        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
-
         centerAboutIcon();
-        if (mMode == PARTIAL_GROW) {
-            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1);
-            PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
-            PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
-            oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
-        } else {
-            PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", mNewSize.width());
-            PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", mNewSize.height());
-            PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", mNewSize.left);
-            PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", mNewSize.top);
-            oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
-            oa.addUpdateListener(new AnimatorUpdateListener() {
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    requestLayout();
-                }
-            });
-
-            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
-            ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
-            alphaOa.setDuration(mExpandDuration);
-            alphaOa.setInterpolator(new AccelerateInterpolator(2.0f));
-            alphaOa.start();
-        }
+        PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1);
+        PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
+        PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
+        ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
 
         oa.addListener(new AnimatorListenerAdapter() {
             @Override
@@ -457,33 +417,10 @@
 
     public void animateClosed() {
         if (!(getParent() instanceof DragLayer)) return;
-
-        ObjectAnimator oa;
-        if (mMode == PARTIAL_GROW) {
-            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
-            PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f);
-            PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f);
-            oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
-        } else {
-            DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
-
-            PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", mIconRect.width());
-            PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", mIconRect.height());
-            PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", mIconRect.left);
-            PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", mIconRect.top);
-            oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
-            oa.addUpdateListener(new AnimatorUpdateListener() {
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    requestLayout();
-                }
-            });
-
-            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
-            ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
-            alphaOa.setDuration(mExpandDuration);
-            alphaOa.setInterpolator(new DecelerateInterpolator(2.0f));
-            alphaOa.start();
-        }
+        PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
+        PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f);
+        PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f);
+        ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
 
         oa.addListener(new AnimatorListenerAdapter() {
             @Override
@@ -791,11 +728,17 @@
         int centeredLeft = centerX - width / 2;
         int centeredTop = centerY - height / 2;
 
+        int currentPage = mLauncher.getWorkspace().getCurrentPage();
+        // In case the workspace is scrolling, we need to use the final scroll to compute
+        // the folders bounds.
+        mLauncher.getWorkspace().setFinalScrollForPageChange(currentPage);
         // We first fetch the currently visible CellLayoutChildren
-        CellLayout currentPage = mLauncher.getWorkspace().getCurrentDropLayout();
-        CellLayoutChildren boundingLayout = currentPage.getChildrenLayout();
+        CellLayout currentLayout = (CellLayout) mLauncher.getWorkspace().getChildAt(currentPage);
+        CellLayoutChildren boundingLayout = currentLayout.getChildrenLayout();
         Rect bounds = new Rect();
         parent.getDescendantRectRelativeToSelf(boundingLayout, bounds);
+        // We reset the workspaces scroll
+        mLauncher.getWorkspace().resetFinalScrollForPageChange(currentPage);
 
         // We need to bound the folder to the currently visible CellLayoutChildren
         int left = Math.min(Math.max(bounds.left, centeredLeft),
@@ -821,14 +764,10 @@
         mFolderIcon.setPivotX(folderIconPivotX);
         mFolderIcon.setPivotY(folderIconPivotY);
 
-        if (mMode == PARTIAL_GROW) {
-            lp.width = width;
-            lp.height = height;
-            lp.x = left;
-            lp.y = top;
-        } else {
-            mNewSize.set(left, top, left + width, top + height);
-        }
+        lp.width = width;
+        lp.height = height;
+        lp.x = left;
+        lp.y = top;
     }
 
     private void setupContentForNumItems(int count) {
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index 3c0829d..2a711f8 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -362,7 +362,7 @@
             dragLayer.animateView(animateView, from, to, finalAlpha,
                     scale * scaleRelativeToDragLayer, DROP_IN_ANIMATION_DURATION,
                     new DecelerateInterpolator(2), new AccelerateInterpolator(2),
-                    postAnimationRunnable, false);
+                    postAnimationRunnable, false, null);
             postDelayed(new Runnable() {
                 public void run() {
                     addItem(item);
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index b7852b3..d74a2c3 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -132,6 +132,7 @@
      * The CellLayout that is currently being dragged over
      */
     private CellLayout mDragTargetLayout = null;
+    private boolean mDragHasEnteredWorkspace = false;
 
     private Launcher mLauncher;
     private IconCache mIconCache;
@@ -2289,10 +2290,8 @@
             mAnimatingViewIntoPlace = true;
             if (d.dragView.hasDrawn()) {
                 int duration = snapScreen < 0 ? -1 : ADJACENT_SCREEN_DROP_DURATION;
-                setFinalScrollForPageChange(snapScreen);
                 mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell, duration,
-                        disableHardwareLayersRunnable);
-                resetFinalScrollForPageChange(snapScreen);
+                        disableHardwareLayersRunnable, this);
             } else {
                 cell.setVisibility(VISIBLE);
             }
@@ -2336,6 +2335,7 @@
     }
 
     public void onDragEnter(DragObject d) {
+        mDragHasEnteredWorkspace = true;
         if (mDragTargetLayout != null) {
             mDragTargetLayout.setIsDragOverlapping(false);
             mDragTargetLayout.onDragExit();
@@ -2371,6 +2371,7 @@
     }
 
     public void onDragExit(DragObject d) {
+        mDragHasEnteredWorkspace = false;
         doDragExit(d);
     }
 
@@ -3240,16 +3241,17 @@
         boolean result = false;
         if (mInScrollArea) {
             if (mDragTargetLayout != null) {
-                // Unmark the overlapping layout and re-enter the current layout
                 mDragTargetLayout.setIsDragOverlapping(false);
-                mDragTargetLayout = getCurrentDropLayout();
-                mDragTargetLayout.onDragEnter();
-
                 // Workspace is responsible for drawing the edge glow on adjacent pages,
                 // so we need to redraw the workspace when this may have changed.
                 invalidate();
-                result = true;
             }
+            if (mDragTargetLayout != null && mDragHasEnteredWorkspace) {
+                // Unmark the overlapping layout and re-enter the current layout
+                mDragTargetLayout = getCurrentDropLayout();
+                mDragTargetLayout.onDragEnter();
+            }
+            result = true;
             mInScrollArea = false;
         }
         return result;