Merge "Polish animation when icon returns to Folder." into ub-launcher3-master
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index fff075e..95f7484 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -2035,7 +2035,7 @@
         if (dropOverView instanceof FolderIcon) {
             FolderIcon fi = (FolderIcon) dropOverView;
             if (fi.acceptDrop(d.dragInfo)) {
-                fi.onDrop(d);
+                fi.onDrop(d, false /* itemReturnedOnFailedDrop */);
 
                 // if the drag started here, we need to remove it from the workspace
                 if (!external) {
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index e182da1..0932b74 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -886,7 +886,7 @@
             mItemsInvalidated = true;
 
             try (SuppressInfoChanges s = new SuppressInfoChanges()) {
-                mFolderIcon.onDrop(d);
+                mFolderIcon.onDrop(d, true /* itemReturnedOnFailedDrop */);
             }
         }
 
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index bb0a726..3998888 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -100,6 +100,7 @@
     ClippedFolderIconLayoutRule mPreviewLayoutRule;
     private PreviewItemManager mPreviewItemManager;
     private PreviewItemDrawingParams mTmpParams = new PreviewItemDrawingParams(0, 0, 0, 0);
+    private List<BubbleTextView> mCurrentPreviewItems = new ArrayList<>();
 
     boolean mAnimating = false;
     private Rect mTempBounds = new Rect();
@@ -198,7 +199,7 @@
     private void setFolder(Folder folder) {
         mFolder = folder;
         mPreviewVerifier = new FolderIconPreviewVerifier(mLauncher.getDeviceProfile().inv);
-        mPreviewItemManager.updateItemDrawingParams(false);
+        updatePreviewItems(false);
     }
 
     private boolean willAcceptItem(ItemInfo item) {
@@ -262,7 +263,8 @@
                 .start();
 
         // This will animate the dragView (srcView) into the new folder
-        onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable);
+        onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable,
+                false /* itemReturnedOnFailedDrop */);
     }
 
     public void performDestroyAnimation(Runnable onCompleteRunnable) {
@@ -277,7 +279,8 @@
     }
 
     private void onDrop(final ShortcutInfo item, DragView animateView, Rect finalRect,
-            float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable) {
+            float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable,
+            boolean itemReturnedOnFailedDrop) {
         item.cellX = -1;
         item.cellY = -1;
 
@@ -305,21 +308,25 @@
                 workspace.resetTransitionTransform((CellLayout) getParent().getParent());
             }
 
+            int numItemsInPreview = Math.min(MAX_NUM_ITEMS_IN_PREVIEW, index + 1);
             boolean itemAdded = false;
-            if (index >= MAX_NUM_ITEMS_IN_PREVIEW) {
-                List<BubbleTextView> oldPreviewItems = getPreviewItemsOnPage(0);
+            if (itemReturnedOnFailedDrop || index >= MAX_NUM_ITEMS_IN_PREVIEW) {
+                List<BubbleTextView> oldPreviewItems = new ArrayList<>(mCurrentPreviewItems);
                 addItem(item, false);
-                List<BubbleTextView> newPreviewItems = getPreviewItemsOnPage(0);
+                mCurrentPreviewItems.clear();
+                mCurrentPreviewItems.addAll(getPreviewItems());
 
-                if (!oldPreviewItems.containsAll(newPreviewItems)) {
-                    for (int i = 0; i < newPreviewItems.size(); ++i) {
-                        if (newPreviewItems.get(i).getTag().equals(item)) {
+                if (!oldPreviewItems.equals(mCurrentPreviewItems)) {
+                    for (int i = 0; i < mCurrentPreviewItems.size(); ++i) {
+                        if (mCurrentPreviewItems.get(i).getTag().equals(item)) {
                             // If the item dropped is going to be in the preview, we update the
                             // index here to reflect its position in the preview.
                             index = i;
                         }
                     }
-                    mPreviewItemManager.onDrop(oldPreviewItems, newPreviewItems, item);
+
+                    mPreviewItemManager.hidePreviewItem(index, true);
+                    mPreviewItemManager.onDrop(oldPreviewItems, mCurrentPreviewItems, item);
                     itemAdded = true;
                 } else {
                     removeItem(item, false);
@@ -331,7 +338,7 @@
             }
 
             int[] center = new int[2];
-            float scale = getLocalCenterForIndex(index, index + 1, center);
+            float scale = getLocalCenterForIndex(index, numItemsInPreview, center);
             center[0] = (int) Math.round(scaleRelativeToDragLayer * center[0]);
             center[1] = (int) Math.round(scaleRelativeToDragLayer * center[1]);
 
@@ -362,7 +369,7 @@
         }
     }
 
-    public void onDrop(DragObject d) {
+    public void onDrop(DragObject d, boolean itemReturnedOnFailedDrop) {
         ShortcutInfo item;
         if (d.dragInfo instanceof AppInfo) {
             // Came from all apps -- make a copy
@@ -374,7 +381,8 @@
             item = (ShortcutInfo) d.dragInfo;
         }
         mFolder.notifyDrop();
-        onDrop(item, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable);
+        onDrop(item, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable,
+                itemReturnedOnFailedDrop);
     }
 
     public void setBadgeInfo(FolderBadgeInfo badgeInfo) {
@@ -545,11 +553,17 @@
 
     @Override
     public void onItemsChanged(boolean animate) {
-        mPreviewItemManager.updateItemDrawingParams(animate);
+        updatePreviewItems(animate);
         invalidate();
         requestLayout();
     }
 
+    private void updatePreviewItems(boolean animate) {
+        mPreviewItemManager.updatePreviewItems(animate);
+        mCurrentPreviewItems.clear();
+        mCurrentPreviewItems.addAll(getPreviewItems());
+    }
+
     @Override
     public void prepareAutoUpdate() {
     }
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
index 5d40010..06d3eb1 100644
--- a/src/com/android/launcher3/folder/PreviewItemManager.java
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -110,7 +110,7 @@
             mIcon.mPreviewLayoutRule.init(mIcon.mBackground.previewSize, mIntrinsicIconSize,
                     Utilities.isRtl(mIcon.getResources()));
 
-            updateItemDrawingParams(false);
+            updatePreviewItems(false);
         }
     }
 
@@ -185,6 +185,11 @@
     }
 
     public void hidePreviewItem(int index, boolean hidden) {
+        // If there are more params than visible in the preview, they are used for enter/exit
+        // animation purposes and they were added to the front of the list.
+        // To index the params properly, we need to skip these params.
+        index = index + Math.max(mFirstPageParams.size() - MAX_NUM_ITEMS_IN_PREVIEW, 0);
+
         PreviewItemDrawingParams params = index < mFirstPageParams.size() ?
                 mFirstPageParams.get(index) : null;
         if (params != null) {
@@ -266,7 +271,7 @@
         }
     }
 
-    void updateItemDrawingParams(boolean animate) {
+    void updatePreviewItems(boolean animate) {
         buildParamsForPage(0, mFirstPageParams, animate);
     }
 
@@ -310,8 +315,8 @@
             int prevIndex = newParams.indexOf(moveIn.get(i));
             PreviewItemDrawingParams p = params.get(prevIndex);
             computePreviewItemDrawingParams(prevIndex, numItems, p);
-            updateTransitionParam(p, moveIn.get(i), ENTER_INDEX,
-                    newParams.indexOf(moveIn.get(i)));
+            updateTransitionParam(p, moveIn.get(i), ENTER_INDEX, newParams.indexOf(moveIn.get(i)),
+                    numItems);
         }
 
         // Items that are moving into new positions within the preview.
@@ -319,7 +324,7 @@
             int oldIndex = oldParams.indexOf(newParams.get(newIndex));
             if (oldIndex >= 0 && newIndex != oldIndex) {
                 PreviewItemDrawingParams p = params.get(newIndex);
-                updateTransitionParam(p, newParams.get(newIndex), oldIndex, newIndex);
+                updateTransitionParam(p, newParams.get(newIndex), oldIndex, newIndex, numItems);
             }
         }
 
@@ -330,7 +335,7 @@
             BubbleTextView item = moveOut.get(i);
             int oldIndex = oldParams.indexOf(item);
             PreviewItemDrawingParams p = computePreviewItemDrawingParams(oldIndex, numItems, null);
-            updateTransitionParam(p, item, oldIndex, EXIT_INDEX);
+            updateTransitionParam(p, item, oldIndex, EXIT_INDEX, numItems);
             params.add(0, p); // We want these items first so that they are on drawn last.
         }
 
@@ -342,7 +347,7 @@
     }
 
     private void updateTransitionParam(final PreviewItemDrawingParams p, BubbleTextView btv,
-            int prevIndex, int newIndex) {
+            int prevIndex, int newIndex, int numItems) {
         p.drawable = btv.getCompoundDrawables()[1];
         if (!mIcon.mFolder.isOpen()) {
             // Set the callback to FolderIcon as it is responsible to drawing the icon. The
@@ -350,9 +355,8 @@
             p.drawable.setCallback(mIcon);
         }
 
-        FolderPreviewItemAnim anim = new FolderPreviewItemAnim(this, p, prevIndex,
-                MAX_NUM_ITEMS_IN_PREVIEW, newIndex, MAX_NUM_ITEMS_IN_PREVIEW,
-                DROP_IN_ANIMATION_DURATION, null);
+        FolderPreviewItemAnim anim = new FolderPreviewItemAnim(this, p, prevIndex, numItems,
+                newIndex, numItems, DROP_IN_ANIMATION_DURATION, null);
         if (p.anim != null && !p.anim.hasEqualFinalState(anim)) {
             p.anim.cancel();
         }