Merge "Fixing broken gradle build" into ub-launcher3-master
diff --git a/res/interpolator/folder_closing_interpolator.xml b/res/interpolator/folder_closing_interpolator.xml
new file mode 100644
index 0000000..e6e012e
--- /dev/null
+++ b/res/interpolator/folder_closing_interpolator.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0.8"
+    android:controlY1="0"
+    android:controlX2="0.8"
+    android:controlY2="1"/>
diff --git a/res/interpolator/folder_opening_interpolator.xml b/res/interpolator/folder_opening_interpolator.xml
new file mode 100644
index 0000000..b95d454
--- /dev/null
+++ b/res/interpolator/folder_opening_interpolator.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0.2"
+    android:controlY1="0"
+    android:controlX2="0"
+    android:controlY2="1"/>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 3b8fb0a..f9a6742 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -590,6 +590,10 @@
                 .isEmpty();
     }
 
+    public int getIconSize() {
+        return mIconSize;
+    }
+
     /**
      * Interface to be implemented by the grand parent to allow click shadow effect.
      */
diff --git a/src/com/android/launcher3/anim/RevealOutlineAnimation.java b/src/com/android/launcher3/anim/RevealOutlineAnimation.java
index 4b270db..51d00d9 100644
--- a/src/com/android/launcher3/anim/RevealOutlineAnimation.java
+++ b/src/com/android/launcher3/anim/RevealOutlineAnimation.java
@@ -83,4 +83,8 @@
     public void getOutline(View v, Outline outline) {
         outline.setRoundRect(mOutline, mOutlineRadius);
     }
+
+    public float getRadius() {
+        return mOutlineRadius;
+    }
 }
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index c63dd58..5b0dfdb 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -46,6 +46,7 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.Alarm;
 import com.android.launcher3.AppInfo;
+import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.CellLayout;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.DragSource;
@@ -82,6 +83,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.List;
 
 /**
  * Represents a set of icons chosen by the user or generated by the system.
@@ -134,8 +136,10 @@
 
     @Thunk final ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
 
+    private FolderAnimationManager mFolderAnimationManager;
+
     private final int mExpandDuration;
-    private final int mMaterialExpandDuration;
+    public final int mMaterialExpandDuration;
     private final int mMaterialExpandStagger;
 
     protected final Launcher mLauncher;
@@ -476,6 +480,8 @@
                 }
             }
         });
+
+        mFolderAnimationManager = new FolderAnimationManager(this);
     }
 
     /**
@@ -512,6 +518,9 @@
     }
 
     private AnimatorSet getOpeningAnimatorSet() {
+        prepareReveal();
+        mFolderIcon.growAndFadeOut();
+
         AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
 
         int width = getFolderWidth();
@@ -602,12 +611,11 @@
         mDeleteFolderOnDropCompleted = false;
 
         final Runnable onCompleteRunnable;
-        prepareReveal();
         centerAboutIcon();
 
-        mFolderIcon.growAndFadeOut();
-
-        AnimatorSet anim = getOpeningAnimatorSet();
+        AnimatorSet anim = FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION
+                ? mFolderAnimationManager.getOpeningAnimator()
+                : getOpeningAnimatorSet();
         onCompleteRunnable = new Runnable() {
             @Override
             public void run() {
@@ -705,7 +713,7 @@
             mFolderName.dispatchBackKey();
         }
 
-        if (mFolderIcon != null) {
+        if (mFolderIcon != null && !FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION) {
             mFolderIcon.shrinkAndFadeIn(animate);
         }
 
@@ -730,12 +738,14 @@
         AnimationLayerSet layerSet = new AnimationLayerSet();
         layerSet.addView(this);
         animatorSet.addListener(layerSet);
-
+        animatorSet.setDuration(mExpandDuration);
         return animatorSet;
     }
 
     private void animateClosed() {
-        AnimatorSet a = getClosingAnimatorSet();
+        AnimatorSet a = FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION
+                ? mFolderAnimationManager.getClosingAnimator()
+                : getClosingAnimatorSet();
         a.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
@@ -750,7 +760,6 @@
                 mState = STATE_ANIMATING;
             }
         });
-        a.setDuration(mExpandDuration);
         a.start();
     }
 
@@ -1453,6 +1462,26 @@
         return mItemsInReadingOrder;
     }
 
+    public List<BubbleTextView> getItemsOnCurrentPage() {
+        ArrayList<View> allItems = getItemsInReadingOrder();
+        int currentPage = mContent.getCurrentPage();
+        int lastPage = mContent.getPageCount() - 1;
+        int totalItemsInFolder = allItems.size();
+        int itemsPerPage = mContent.itemsPerPage();
+        int numItemsOnCurrentPage = currentPage == lastPage
+                ? totalItemsInFolder - (itemsPerPage * currentPage)
+                : itemsPerPage;
+
+        int startIndex = currentPage * itemsPerPage;
+        int endIndex = startIndex + numItemsOnCurrentPage;
+
+        List<BubbleTextView> itemsOnCurrentPage = new ArrayList<>(numItemsOnCurrentPage);
+        for (int i = startIndex; i < endIndex; ++i) {
+            itemsOnCurrentPage.add((BubbleTextView) allItems.get(i));
+        }
+        return itemsOnCurrentPage;
+    }
+
     public void onFocusChange(View v, boolean hasFocus) {
         if (v == mFolderName) {
             if (hasFocus) {
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
new file mode 100644
index 0000000..d14bb40
--- /dev/null
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.folder;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.GradientDrawable;
+import android.support.v4.graphics.ColorUtils;
+import android.util.Property;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.CellLayout;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAnimUtils;
+import com.android.launcher3.R;
+import com.android.launcher3.ShortcutAndWidgetContainer;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
+import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.util.Themes;
+
+import java.util.List;
+
+/**
+ * Manages the opening and closing animations for a {@link Folder}.
+ *
+ * All of the animations are done in the Folder.
+ * ie. When the user taps on the FolderIcon, we immediately hide the FolderIcon and show the Folder
+ * in its place before starting the animation.
+ */
+public class FolderAnimationManager {
+
+    private Folder mFolder;
+    private FolderPagedView mContent;
+    private GradientDrawable mFolderBackground;
+
+    private FolderIcon mFolderIcon;
+    private FolderIcon.PreviewBackground mPreviewBackground;
+
+    private Context mContext;
+    private Launcher mLauncher;
+
+    private Animator mRevealAnimator;
+    private final TimeInterpolator mOpeningInterpolator;
+    private final TimeInterpolator mClosingInterpolator;
+
+    private final FolderIcon.PreviewItemDrawingParams mTmpParams =
+            new FolderIcon.PreviewItemDrawingParams(0, 0, 0, 0);
+
+    private static final Property<View, Float> SCALE_PROPERTY =
+            new Property<View, Float>(Float.class, "scale") {
+                @Override
+                public Float get(View view) {
+                    return view.getScaleX();
+                }
+
+                @Override
+                public void set(View view, Float scale) {
+                    view.setScaleX(scale);
+                    view.setScaleY(scale);
+                }
+            };
+
+    private static final Property<List<BubbleTextView>, Integer> ITEMS_TEXT_COLOR_PROPERTY =
+            new Property<List<BubbleTextView>, Integer>(Integer.class, "textColor") {
+                @Override
+                public Integer get(List<BubbleTextView> items) {
+                    return items.get(0).getCurrentTextColor();
+                }
+
+                @Override
+                public void set(List<BubbleTextView> items, Integer color) {
+                    int size = items.size();
+
+                    for (int i = 0; i < size; ++i) {
+                        items.get(i).setTextColor(color);
+                    }
+                }
+            };
+
+    public FolderAnimationManager(Folder folder) {
+        mFolder = folder;
+        mContent = folder.mContent;
+        mFolderBackground = (GradientDrawable) mFolder.getBackground();
+
+        mFolderIcon = folder.mFolderIcon;
+        mPreviewBackground = mFolderIcon.mBackground;
+
+        mContext = folder.getContext();
+        mLauncher = folder.mLauncher;
+
+        mOpeningInterpolator = AnimationUtils.loadInterpolator(mContext,
+                R.interpolator.folder_opening_interpolator);
+        mClosingInterpolator = AnimationUtils.loadInterpolator(mContext,
+                R.interpolator.folder_closing_interpolator);
+    }
+
+    public AnimatorSet getOpeningAnimator() {
+        mFolder.setPivotX(0);
+        mFolder.setPivotY(0);
+
+        AnimatorSet a = getAnimatorSet(true /* isOpening */);
+        a.setInterpolator(mOpeningInterpolator);
+        a.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mFolderIcon.setVisibility(View.INVISIBLE);
+            }
+        });
+        return a;
+    }
+
+    public AnimatorSet getClosingAnimator() {
+        AnimatorSet a = getAnimatorSet(false /* isOpening */);
+        a.setInterpolator(mClosingInterpolator);
+        a.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mFolderIcon.setVisibility(View.VISIBLE);
+            }
+        });
+        return a;
+    }
+
+    /**
+     * Prepares the Folder for animating between open / closed states.
+     *
+     * @param isOpening If true, return the animator set for the opening animation.
+     */
+    private AnimatorSet getAnimatorSet(final boolean isOpening) {
+        final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) mFolder.getLayoutParams();
+        FolderIcon.PreviewLayoutRule rule = mFolderIcon.getLayoutRule();
+        final List<BubbleTextView> itemsInPreview = mFolderIcon.getItemsToDisplay();
+
+        // Match size/scale of icons in the preview
+        float previewScale = rule.scaleForItem(0, itemsInPreview.size());
+        float previewSize = rule.getIconSize() * previewScale;
+        float folderScale = previewSize / itemsInPreview.get(0).getIconSize();
+
+        final float initialScale = folderScale;
+        final float finalScale = 1f;
+        float scale = isOpening ? initialScale : finalScale;
+        mFolder.setScaleX(scale);
+        mFolder.setScaleY(scale);
+
+        // Match position of the FolderIcon
+        final Rect folderIconPos = new Rect();
+        float scaleRelativeToDragLayer = mLauncher.getDragLayer()
+                .getDescendantRectRelativeToSelf(mFolderIcon, folderIconPos);
+        folderScale *= scaleRelativeToDragLayer;
+
+        // We want to create a small X offset for the preview items, so that they follow their
+        // expected path to their final locations. ie. an icon should not move right, if it's final
+        // location is to its left. This value is arbitrarily defined.
+        final int nudgeOffsetX = (int) (previewSize / 2);
+
+        final int paddingOffsetX = (int) ((mFolder.getPaddingLeft() + mContent.getPaddingLeft())
+                * folderScale);
+        final int paddingOffsetY = (int) ((mFolder.getPaddingTop() + mContent.getPaddingTop())
+                * folderScale);
+
+        int initialX = folderIconPos.left + mFolderIcon.mBackground.getOffsetX() - paddingOffsetX
+                - nudgeOffsetX;
+        int initialY = folderIconPos.top + mFolderIcon.mBackground.getOffsetY() - paddingOffsetY;
+        final float xDistance = initialX - lp.x;
+        final float yDistance = initialY - lp.y;
+
+        // Set up the Folder background.
+        final int finalColor = Themes.getAttrColor(mContext, android.R.attr.colorPrimary);
+        final int initialColor =
+                ColorUtils.setAlphaComponent(finalColor, mPreviewBackground.getBackgroundAlpha());
+        mFolderBackground.setColor(isOpening ? initialColor : finalColor);
+
+        // Initialize the Folder items' text.
+        final List<BubbleTextView> itemsOnCurrentPage = mFolder.getItemsOnCurrentPage();
+        final int finalTextColor = Themes.getAttrColor(mContext, android.R.attr.textColorSecondary);
+        ITEMS_TEXT_COLOR_PROPERTY.set(itemsOnCurrentPage, isOpening ? Color.TRANSPARENT
+                : finalTextColor);
+
+        // Create the animators.
+        AnimatorSet a = LauncherAnimUtils.createAnimatorSet();
+        a.setDuration(mFolder.mMaterialExpandDuration);
+
+        ObjectAnimator translationX = isOpening
+                ? ObjectAnimator.ofFloat(mFolder, View.TRANSLATION_X, xDistance, 0)
+                : ObjectAnimator.ofFloat(mFolder, View.TRANSLATION_X, 0, xDistance);
+        a.play(translationX);
+
+        ObjectAnimator translationY = isOpening
+                ? ObjectAnimator.ofFloat(mFolder, View.TRANSLATION_Y, yDistance, 0)
+                : ObjectAnimator.ofFloat(mFolder, View.TRANSLATION_Y, 0, yDistance);
+        a.play(translationY);
+
+        ObjectAnimator scaleAnimator = isOpening
+                ? ObjectAnimator.ofFloat(mFolder, SCALE_PROPERTY, initialScale, finalScale)
+                : ObjectAnimator.ofFloat(mFolder, SCALE_PROPERTY, finalScale, initialScale);
+        a.play(scaleAnimator);
+
+        ObjectAnimator itemsTextColor = isOpening
+                ? ObjectAnimator.ofArgb(itemsOnCurrentPage, ITEMS_TEXT_COLOR_PROPERTY,
+                        Color.TRANSPARENT, finalTextColor)
+                : ObjectAnimator.ofArgb(itemsOnCurrentPage, ITEMS_TEXT_COLOR_PROPERTY,
+                        finalTextColor, Color.TRANSPARENT);
+        a.play(itemsTextColor);
+
+        ObjectAnimator backgroundColor = isOpening
+                ? ObjectAnimator.ofArgb(mFolderBackground, "color", initialColor, finalColor)
+                : ObjectAnimator.ofArgb(mFolderBackground, "color", finalColor, initialColor);
+        a.play(backgroundColor);
+
+        // Set up the reveal animation that clips the Folder.
+        float stroke = mPreviewBackground.getStrokeWidth();
+        int initialSize = (int) ((mFolderIcon.mBackground.getRadius() * 2 + stroke) / folderScale);
+        int totalOffsetX = paddingOffsetX + Math.round(nudgeOffsetX / folderScale);
+        int unscaledStroke = (int) Math.floor(stroke / folderScale);
+        Rect startRect = new Rect(totalOffsetX + unscaledStroke, unscaledStroke,
+                totalOffsetX + initialSize, initialSize);
+        Rect endRect = new Rect(0, 0, lp.width, lp.height);
+        a.play(getRevealAnimator(isOpening, initialSize / 2f, startRect, endRect));
+
+        a.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                ITEMS_TEXT_COLOR_PROPERTY.set(itemsOnCurrentPage, finalTextColor);
+            }
+        });
+
+        addPreviewItemAnimatorsToSet(a, isOpening, folderScale, nudgeOffsetX);
+        return a;
+    }
+
+    private Animator getRevealAnimator(boolean isOpening, float circleRadius, Rect start,
+            Rect end) {
+        boolean revealIsRunning = mRevealAnimator != null && mRevealAnimator.isRunning();
+        final float finalRadius = revealIsRunning
+                ? ((RoundedRectRevealOutlineProvider) mFolder.getOutlineProvider()).getRadius()
+                : Utilities.pxFromDp(2, mContext.getResources().getDisplayMetrics());
+        if (revealIsRunning) {
+            mRevealAnimator.cancel();
+        }
+        mRevealAnimator = new RoundedRectRevealOutlineProvider(circleRadius, finalRadius,
+                start, end).createRevealAnimator(mFolder, !isOpening);
+        return mRevealAnimator;
+    }
+
+    /**
+     * Animate the items that are displayed in the preview.
+     */
+    private void addPreviewItemAnimatorsToSet(AnimatorSet animatorSet, boolean isOpening,
+            final float folderScale, int nudgeOffsetX) {
+        FolderIcon.PreviewLayoutRule rule = mFolderIcon.getLayoutRule();
+        final List<BubbleTextView> itemsInPreview = mFolderIcon.getItemsToDisplay();
+        final int numItemsInPreview = itemsInPreview.size();
+
+        ShortcutAndWidgetContainer cwc = mContent.getPageAt(0).getShortcutsAndWidgets();
+        for (int i = 0; i < numItemsInPreview; ++i) {
+            final BubbleTextView btv = itemsInPreview.get(i);
+            CellLayout.LayoutParams btvLp = (CellLayout.LayoutParams) btv.getLayoutParams();
+
+            // Calculate the final values in the LayoutParams.
+            btvLp.isLockedToGrid = true;
+            cwc.setupLp(btv);
+
+            // Match scale of icons in the preview.
+            float previewScale = rule.scaleForItem(i, numItemsInPreview);
+            float previewSize = rule.getIconSize() * previewScale;
+            float iconScale = previewSize / itemsInPreview.get(i).getIconSize();
+
+            final float initialScale = iconScale / folderScale;
+            final float finalScale = 1f;
+            float scale = isOpening ? initialScale : finalScale;
+            btv.setScaleX(scale);
+            btv.setScaleY(scale);
+
+            // Match positions of the icons in the folder with their positions in the preview
+            rule.computePreviewItemDrawingParams(i, numItemsInPreview, mTmpParams);
+            // The PreviewLayoutRule assumes that the icon size takes up the entire width so we
+            // offset by the actual size.
+            int iconOffsetX = (int) ((btvLp.width - btv.getIconSize()) * iconScale) / 2;
+
+            final int previewPosX =
+                    (int) ((mTmpParams.transX - iconOffsetX + nudgeOffsetX) / folderScale);
+            final int previewPosY = (int) (mTmpParams.transY / folderScale);
+
+            final float xDistance = previewPosX - btvLp.x;
+            final float yDistance = previewPosY - btvLp.y;
+
+            ObjectAnimator translationX = isOpening
+                    ? ObjectAnimator.ofFloat(btv, View.TRANSLATION_X, xDistance, 0)
+                    : ObjectAnimator.ofFloat(btv, View.TRANSLATION_X, 0, xDistance);
+            animatorSet.play(translationX);
+
+            ObjectAnimator translationY = isOpening
+                    ? ObjectAnimator.ofFloat(btv, View.TRANSLATION_Y, yDistance, 0)
+                    : ObjectAnimator.ofFloat(btv, View.TRANSLATION_Y, 0, yDistance);
+            animatorSet.play(translationY);
+
+            ObjectAnimator scaleAnimator = isOpening
+                    ? ObjectAnimator.ofFloat(btv, SCALE_PROPERTY, initialScale, finalScale)
+                    : ObjectAnimator.ofFloat(btv, SCALE_PROPERTY, finalScale, initialScale);
+            animatorSet.play(scaleAnimator);
+
+            animatorSet.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    super.onAnimationEnd(animation);
+                    btv.setTranslationX(0.0f);
+                    btv.setTranslationY(0.0f);
+                    btv.setScaleX(1f);
+                    btv.setScaleY(1f);
+                }
+            });
+        }
+    }
+}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 92577b7..9395572 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -407,6 +407,10 @@
         mBadgeInfo = badgeInfo;
     }
 
+    public PreviewLayoutRule getLayoutRule() {
+        return mPreviewLayoutRule;
+    }
+
     /**
      * Sets mBadgeScale to 1 or 0, animating if oldCount or newCount is 0
      * (the badge is being added or removed).
@@ -824,6 +828,14 @@
             };
             animateScale(1f, 1f, onStart, onEnd);
         }
+
+        public int getBackgroundAlpha() {
+            return (int) Math.min(MAX_BG_OPACITY, BG_OPACITY * mColorMultiplier);
+        }
+
+        public float getStrokeWidth() {
+            return mStrokeWidth;
+        }
     }
 
     public void setFolderBackground(PreviewBackground bg) {
@@ -991,15 +1003,15 @@
         return mFolderName.getVisibility() == VISIBLE;
     }
 
-    private List<View> getItemsToDisplay() {
+    public List<BubbleTextView> getItemsToDisplay() {
         mPreviewVerifier.setFolderInfo(mFolder.getInfo());
 
-        List<View> itemsToDisplay = new ArrayList<>();
+        List<BubbleTextView> itemsToDisplay = new ArrayList<>();
         List<View> allItems = mFolder.getItemsInReadingOrder();
         int numItems = allItems.size();
         for (int rank = 0; rank < numItems; ++rank) {
             if (mPreviewVerifier.isItemInPreview(rank)) {
-                itemsToDisplay.add(allItems.get(rank));
+                itemsToDisplay.add((BubbleTextView) allItems.get(rank));
             }
 
             if (itemsToDisplay.size() == FolderIcon.NUM_ITEMS_IN_PREVIEW) {
@@ -1010,7 +1022,7 @@
     }
 
     private void updateItemDrawingParams(boolean animate) {
-        List<View> items = getItemsToDisplay();
+        List<BubbleTextView> items = getItemsToDisplay();
         int nItemsInPreview = items.size();
 
         int prevNumItems = mDrawingParams.size();
@@ -1025,7 +1037,7 @@
 
         for (int i = 0; i < mDrawingParams.size(); i++) {
             PreviewItemDrawingParams p = mDrawingParams.get(i);
-            p.drawable = ((TextView) items.get(i)).getCompoundDrawables()[1];
+            p.drawable = items.get(i).getCompoundDrawables()[1];
 
             if (!animate || FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON) {
                 computePreviewItemDrawingParams(i, nItemsInPreview, p);
diff --git a/src_config/com/android/launcher3/config/FeatureFlags.java b/src_config/com/android/launcher3/config/FeatureFlags.java
index 80eebec..d9b7433 100644
--- a/src_config/com/android/launcher3/config/FeatureFlags.java
+++ b/src_config/com/android/launcher3/config/FeatureFlags.java
@@ -28,7 +28,7 @@
     public static boolean LAUNCHER3_USE_SYSTEM_DRAG_DRIVER = true;
     public static boolean LAUNCHER3_DISABLE_PINCH_TO_OVERVIEW = false;
     public static boolean LAUNCHER3_ALL_APPS_PULL_UP = true;
-    public static boolean LAUNCHER3_NEW_FOLDER_ANIMATION = false;
+    public static boolean LAUNCHER3_NEW_FOLDER_ANIMATION = true;
     // When enabled allows to use any point on the fast scrollbar to start dragging.
     public static boolean LAUNCHER3_DIRECT_SCROLL = true;
     // When enabled while all-apps open, the soft input will be set to adjust resize .