Updating folder UI

> Removing 2 folder content implementations and merging unscrollable
content into FolderPagedView
> Disaling folder sorting
> Fixing pageIndicator height

Change-Id: I36e35e311eaf99b6c69d450c0765bd41b2d68738
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index 1e1d1ee..0eb1fd8 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -69,7 +69,6 @@
      * results in CellLayout being measured as UNSPECIFIED, which it does not support.
      */
     private static final int MIN_CONTENT_DIMEN = 5;
-    private static final boolean ALLOW_FOLDER_SCROLL = true;
 
     static final int STATE_NONE = -1;
     static final int STATE_SMALL = 0;
@@ -101,6 +100,8 @@
 
     private final Alarm mReorderAlarm = new Alarm();
     private final Alarm mOnExitAlarm = new Alarm();
+    private final Alarm mOnScrollHintAlarm = new Alarm();
+    @Thunk final Alarm mScrollPauseAlarm = new Alarm();
 
     @Thunk final ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
 
@@ -116,7 +117,7 @@
 
     @Thunk FolderIcon mFolderIcon;
 
-    @Thunk FolderContent mContent;
+    @Thunk FolderPagedView mContent;
     @Thunk View mContentWrapper;
     FolderEditText mFolderName;
 
@@ -149,11 +150,6 @@
 
     // Folder scrolling
     private int mScrollAreaOffset;
-    private Alarm mOnScrollHintAlarm;
-    @Thunk Alarm mScrollPauseAlarm;
-
-    // TODO: Use {@link #mContent} once {@link #ALLOW_FOLDER_SCROLL} is removed.
-    @Thunk FolderPagedView mPagedView;
 
     @Thunk int mScrollHintDir = DragController.SCROLL_NONE;
     @Thunk int mCurrentScrollDir = DragController.SCROLL_NONE;
@@ -186,18 +182,13 @@
         // name is complete, we have something to focus on, thus hiding the cursor and giving
         // reliable behavior when clicking the text field (since it will always gain focus on click).
         setFocusableInTouchMode(true);
-
-        if (ALLOW_FOLDER_SCROLL) {
-            mOnScrollHintAlarm = new Alarm();
-            mScrollPauseAlarm = new Alarm();
-        }
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
         mContentWrapper = findViewById(R.id.folder_content_wrapper);
-        mContent = (FolderContent) findViewById(R.id.folder_content);
+        mContent = (FolderPagedView) findViewById(R.id.folder_content);
         mContent.setFolder(this);
 
         mFolderName = (FolderEditText) findViewById(R.id.folder_name);
@@ -211,16 +202,16 @@
         mFolderName.setInputType(mFolderName.getInputType() |
                 InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
 
-        mFooter = ALLOW_FOLDER_SCROLL ? findViewById(R.id.folder_footer) : mFolderName;
+        mFooter = findViewById(R.id.folder_footer);
+        updateFooterHeight();
+    }
+
+    public void updateFooterHeight() {
         // We find out how tall footer wants to be (it is set to wrap_content), so that
         // we can allocate the appropriate amount of space for it.
         int measureSpec = MeasureSpec.UNSPECIFIED;
         mFooter.measure(measureSpec, measureSpec);
         mFooterHeight = mFooter.getMeasuredHeight();
-
-        if (ALLOW_FOLDER_SCROLL) {
-            mPagedView = (FolderPagedView) mContent;
-        }
     }
 
     private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
@@ -398,8 +389,7 @@
      * @return A new UserFolder.
      */
     static Folder fromXml(Context context) {
-        return (Folder) LayoutInflater.from(context).inflate(
-                ALLOW_FOLDER_SCROLL ? R.layout.user_folder_scroll : R.layout.user_folder, null);
+        return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
     }
 
     /**
@@ -424,12 +414,10 @@
     public void animateOpen() {
         if (!(getParent() instanceof DragLayer)) return;
 
-        if (ALLOW_FOLDER_SCROLL) {
-            mPagedView.completePendingPageChanges();
-            if (!(mDragInProgress && mPagedView.mIsSorted)) {
-                // Open on the first page.
-                mPagedView.snapToPageImmediately(0);
-            }
+        mContent.completePendingPageChanges();
+        if (!(mDragInProgress && mContent.mIsSorted)) {
+            // Open on the first page.
+            mContent.snapToPageImmediately(0);
         }
 
         Animator openFolderAnim = null;
@@ -533,10 +521,8 @@
             mDragController.forceTouchMove();
         }
 
-        if (ALLOW_FOLDER_SCROLL) {
-            FolderPagedView pages = (FolderPagedView) mContent;
-            pages.verifyVisibleHighResIcons(pages.getNextPage());
-        }
+        FolderPagedView pages = (FolderPagedView) mContent;
+        pages.verifyVisibleHighResIcons(pages.getNextPage());
     }
 
     public void beginExternalDrag(ShortcutInfo item) {
@@ -544,7 +530,8 @@
         mEmptyCellRank = mContent.allocateRankForNewItem(item);
         mIsExternalDrag = true;
         mDragInProgress = true;
-        if (ALLOW_FOLDER_SCROLL && mPagedView.mIsSorted) {
+
+        if (mContent.mIsSorted) {
             mScrollPauseAlarm.setOnAlarmListener(null);
             mScrollPauseAlarm.cancelAlarm();
             mScrollPauseAlarm.setAlarm(SORTED_STICKY_REORDER_DELAY);
@@ -601,11 +588,9 @@
     public void onDragEnter(DragObject d) {
         mPrevTargetRank = -1;
         mOnExitAlarm.cancelAlarm();
-        if (ALLOW_FOLDER_SCROLL) {
-            // Get the area offset such that the folder only closes if half the drag icon width
-            // is outside the folder area
-            mScrollAreaOffset = d.dragView.getDragRegionWidth() / 2 - d.xOffset;
-        }
+        // Get the area offset such that the folder only closes if half the drag icon width
+        // is outside the folder area
+        mScrollAreaOffset = d.dragView.getDragRegionWidth() / 2 - d.xOffset;
     }
 
     OnAlarmListener mReorderAlarmListener = new OnAlarmListener() {
@@ -632,7 +617,7 @@
     }
 
     @Thunk void onDragOver(DragObject d, int reorderDelay) {
-        if (ALLOW_FOLDER_SCROLL && mScrollPauseAlarm.alarmPending()) {
+        if (mScrollPauseAlarm.alarmPending()) {
             return;
         }
         final float[] r = new float[2];
@@ -645,27 +630,23 @@
             mPrevTargetRank = mTargetRank;
         }
 
-        if (!ALLOW_FOLDER_SCROLL) {
-            return;
-        }
-
         float x = r[0];
-        int currentPage = mPagedView.getNextPage();
+        int currentPage = mContent.getNextPage();
 
-        float cellOverlap = mPagedView.getCurrentCellLayout().getCellWidth()
+        float cellOverlap = mContent.getCurrentCellLayout().getCellWidth()
                 * ICON_OVERSCROLL_WIDTH_FACTOR;
         boolean isOutsideLeftEdge = x < cellOverlap;
         boolean isOutsideRightEdge = x > (getWidth() - cellOverlap);
 
-        if (currentPage > 0 && (mPagedView.rtlLayout ? isOutsideRightEdge : isOutsideLeftEdge)) {
+        if (currentPage > 0 && (mContent.rtlLayout ? isOutsideRightEdge : isOutsideLeftEdge)) {
             showScrollHint(DragController.SCROLL_LEFT, d);
-        } else if (currentPage < (mPagedView.getPageCount() - 1)
-                && (mPagedView.rtlLayout ? isOutsideLeftEdge : isOutsideRightEdge)) {
+        } else if (currentPage < (mContent.getPageCount() - 1)
+                && (mContent.rtlLayout ? isOutsideLeftEdge : isOutsideRightEdge)) {
             showScrollHint(DragController.SCROLL_RIGHT, d);
         } else {
             mOnScrollHintAlarm.cancelAlarm();
             if (mScrollHintDir != DragController.SCROLL_NONE) {
-                mPagedView.clearScrollHint();
+                mContent.clearScrollHint();
                 mScrollHintDir = DragController.SCROLL_NONE;
             }
         }
@@ -674,7 +655,7 @@
     private void showScrollHint(int direction, DragObject d) {
         // Show scroll hint on the right
         if (mScrollHintDir != direction) {
-            mPagedView.showScrollHint(direction);
+            mContent.showScrollHint(direction);
             mScrollHintDir = direction;
         }
 
@@ -714,13 +695,11 @@
         }
         mReorderAlarm.cancelAlarm();
 
-        if (ALLOW_FOLDER_SCROLL) {
-            mOnScrollHintAlarm.cancelAlarm();
-            mScrollPauseAlarm.cancelAlarm();
-            if (mScrollHintDir != DragController.SCROLL_NONE) {
-                mPagedView.clearScrollHint();
-                mScrollHintDir = DragController.SCROLL_NONE;
-            }
+        mOnScrollHintAlarm.cancelAlarm();
+        mScrollPauseAlarm.cancelAlarm();
+        if (mScrollHintDir != DragController.SCROLL_NONE) {
+            mContent.clearScrollHint();
+            mScrollHintDir = DragController.SCROLL_NONE;
         }
     }
 
@@ -1088,21 +1067,19 @@
             };
         }
 
-        if (ALLOW_FOLDER_SCROLL) {
-            // If the icon was dropped while the page was being scrolled, we need to compute
-            // the target location again such that the icon is placed of the final page.
-            if (!mPagedView.rankOnCurrentPage(mEmptyCellRank)) {
-                // Reorder again.
-                mTargetRank = getTargetRank(d, null);
+        // If the icon was dropped while the page was being scrolled, we need to compute
+        // the target location again such that the icon is placed of the final page.
+        if (!mContent.rankOnCurrentPage(mEmptyCellRank)) {
+            // Reorder again.
+            mTargetRank = getTargetRank(d, null);
 
-                // Rearrange items immediately.
-                mReorderAlarmListener.onAlarm(mReorderAlarm);
+            // Rearrange items immediately.
+            mReorderAlarmListener.onAlarm(mReorderAlarm);
 
-                mOnScrollHintAlarm.cancelAlarm();
-                mScrollPauseAlarm.cancelAlarm();
-            }
-            mPagedView.completePendingPageChanges();
+            mOnScrollHintAlarm.cancelAlarm();
+            mScrollPauseAlarm.cancelAlarm();
         }
+        mContent.completePendingPageChanges();
 
         View currentDragView;
         ShortcutInfo si = mCurrentDragInfo;
@@ -1252,10 +1229,10 @@
         @Override
         public void onAlarm(Alarm alarm) {
             if (mCurrentScrollDir == DragController.SCROLL_LEFT) {
-                mPagedView.scrollLeft();
+                mContent.scrollLeft();
                 mScrollHintDir = DragController.SCROLL_NONE;
             } else if (mCurrentScrollDir == DragController.SCROLL_RIGHT) {
-                mPagedView.scrollRight();
+                mContent.scrollRight();
                 mScrollHintDir = DragController.SCROLL_NONE;
             } else {
                 // This should not happen
@@ -1286,69 +1263,4 @@
             onDragOver(mDragObject, 1);
         }
     }
-
-    public static interface FolderContent {
-        void setFolder(Folder f);
-
-        void removeItem(View v);
-
-        boolean isFull();
-        int getItemCount();
-
-        int getDesiredWidth();
-        int getDesiredHeight();
-        void setFixedSize(int width, int height);
-
-        /**
-         * Iterates over all its items in a reading order.
-         * @return the view for which the operator returned true.
-         */
-        View iterateOverItems(ItemOperator op);
-        View getLastItem();
-
-        String getAccessibilityDescription();
-
-        /**
-         * Binds items to the layout.
-         * @return list of items that could not be bound, probably because we hit the max size limit.
-         */
-        ArrayList<ShortcutInfo> bindItems(ArrayList<ShortcutInfo> children);
-
-        /**
-         * Create space for a new item, and returns the rank for that item.
-         * Resizes the content if necessary.
-         */
-        int allocateRankForNewItem(ShortcutInfo info);
-
-        View createAndAddViewForRank(ShortcutInfo item, int rank);
-
-        /**
-         * Adds the {@param view} to the layout based on {@param rank} and updated the position
-         * related attributes. It assumes that {@param item} is already attached to the view.
-         */
-        void addViewForRank(View view, ShortcutInfo item, int rank);
-
-        /**
-         * Reorders the items such that the {@param empty} spot moves to {@param target}
-         */
-        void realTimeReorder(int empty, int target);
-
-        /**
-         * @return the rank of the cell nearest to the provided pixel position.
-         */
-        int findNearestArea(int pixelX, int pixelY);
-
-        /**
-         * Updates position and rank of all the children in the view based.
-         * @param list the ordered list of children.
-         * @param itemCount if greater than the total children count, empty spaces are left
-         * at the end.
-         */
-        void arrangeChildren(ArrayList<View> list, int itemCount);
-
-        /**
-         * Sets the focus on the first visible child.
-         */
-        void setFocusOnFirstChild();
-    }
 }
diff --git a/src/com/android/launcher3/FolderCellLayout.java b/src/com/android/launcher3/FolderCellLayout.java
deleted file mode 100644
index 8585add..0000000
--- a/src/com/android/launcher3/FolderCellLayout.java
+++ /dev/null
@@ -1,330 +0,0 @@
-/**
- * Copyright (C) 2015 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;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.android.launcher3.Workspace.ItemOperator;
-
-import java.util.ArrayList;
-
-public class FolderCellLayout extends CellLayout implements Folder.FolderContent {
-
-    private static final int REORDER_ANIMATION_DURATION = 230;
-    private static final int START_VIEW_REORDER_DELAY = 30;
-    private static final float VIEW_REORDER_DELAY_FACTOR = 0.9f;
-
-    private static final int[] sTempPosArray = new int[2];
-
-    private final FolderKeyEventListener mKeyListener = new FolderKeyEventListener();
-    private final LayoutInflater mInflater;
-    private final IconCache mIconCache;
-
-    private final int mMaxCountX;
-    private final int mMaxCountY;
-    private final int mMaxNumItems;
-
-    // Indicates the last number of items used to set up the grid size
-    private int mAllocatedContentSize;
-
-    private Folder mFolder;
-    private FocusIndicatorView mFocusIndicatorView;
-
-    public FolderCellLayout(Context context) {
-        this(context, null);
-    }
-
-    public FolderCellLayout(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public FolderCellLayout(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-
-        LauncherAppState app = LauncherAppState.getInstance();
-        DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-        mMaxCountX = (int) grid.numColumns;
-        mMaxCountY = (int) grid.numRows;
-        mMaxNumItems = mMaxCountX * mMaxCountY;
-
-        mInflater = LayoutInflater.from(context);
-        mIconCache = app.getIconCache();
-
-        setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx);
-        getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
-        setInvertIfRtl(true);
-    }
-
-    @Override
-    public void setFolder(Folder folder) {
-        mFolder = folder;
-        mFocusIndicatorView = (FocusIndicatorView) folder.findViewById(R.id.focus_indicator);
-    }
-
-    /**
-     * Sets up the grid size such that {@param count} items can fit in the grid.
-     * The grid size is calculated such that countY <= countX and countX = ceil(sqrt(count)) while
-     * maintaining the restrictions of {@link #mMaxCountX} &amp; {@link #mMaxCountY}.
-     */
-    private void setupContentDimensions(int count) {
-        mAllocatedContentSize = count;
-        int countX = getCountX();
-        int countY = getCountY();
-        boolean done = false;
-
-        while (!done) {
-            int oldCountX = countX;
-            int oldCountY = countY;
-            if (countX * countY < count) {
-                // Current grid is too small, expand it
-                if ((countX <= countY || countY == mMaxCountY) && countX < mMaxCountX) {
-                    countX++;
-                } else if (countY < mMaxCountY) {
-                    countY++;
-                }
-                if (countY == 0) countY++;
-            } else if ((countY - 1) * countX >= count && countY >= countX) {
-                countY = Math.max(0, countY - 1);
-            } else if ((countX - 1) * countY >= count) {
-                countX = Math.max(0, countX - 1);
-            }
-            done = countX == oldCountX && countY == oldCountY;
-        }
-        setGridSize(countX, countY);
-    }
-
-    @Override
-    public ArrayList<ShortcutInfo> bindItems(ArrayList<ShortcutInfo> items) {
-        ArrayList<ShortcutInfo> extra = new ArrayList<ShortcutInfo>();
-        setupContentDimensions(Math.min(items.size(), mMaxNumItems));
-
-        int countX = getCountX();
-        int rank = 0;
-        for (ShortcutInfo item : items) {
-            if (rank >= mMaxNumItems) {
-                extra.add(item);
-                continue;
-            }
-
-            item.rank = rank;
-            item.cellX = rank % countX;
-            item.cellY = rank / countX;
-            addNewView(item);
-            rank++;
-        }
-        return extra;
-    }
-
-    @Override
-    public int allocateRankForNewItem(ShortcutInfo info) {
-        int rank = getItemCount();
-        mFolder.rearrangeChildren(rank + 1);
-        return rank;
-    }
-
-    @Override
-    public View createAndAddViewForRank(ShortcutInfo item, int rank) {
-        updateItemXY(item, rank);
-        return addNewView(item);
-    }
-
-    @Override
-    public void addViewForRank(View view, ShortcutInfo item, int rank) {
-        updateItemXY(item, rank);
-        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
-        lp.cellX = item.cellX;
-        lp.cellY = item.cellY;
-        addViewToCellLayout(view, -1, mFolder.mLauncher.getViewIdForItem(item), lp, true);
-    }
-
-    @Override
-    public void removeItem(View v) {
-        removeView(v);
-    }
-
-    /**
-     * Updates the item cellX and cellY position
-     */
-    private void updateItemXY(ShortcutInfo item, int rank) {
-        item.rank = rank;
-        int countX = getCountX();
-        item.cellX = rank % countX;
-        item.cellY = rank / countX;
-    }
-
-    private View addNewView(ShortcutInfo item) {
-        final BubbleTextView textView = (BubbleTextView) mInflater.inflate(
-                R.layout.folder_application, getShortcutsAndWidgets(), false);
-        textView.applyFromShortcutInfo(item, mIconCache, false);
-        textView.setOnClickListener(mFolder);
-        textView.setOnLongClickListener(mFolder);
-        textView.setOnFocusChangeListener(mFocusIndicatorView);
-        textView.setOnKeyListener(mKeyListener);
-
-        CellLayout.LayoutParams lp = new CellLayout.LayoutParams(
-                item.cellX, item.cellY, item.spanX, item.spanY);
-        addViewToCellLayout(textView, -1, mFolder.mLauncher.getViewIdForItem(item), lp, true);
-        return textView;
-    }
-
-    /**
-     * Refer {@link #findNearestArea(int, int, int, int, View, boolean, int[])}
-     */
-    @Override
-    public int findNearestArea(int pixelX, int pixelY) {
-        findNearestArea(pixelX, pixelY, 1, 1, null, false, sTempPosArray);
-        if (mFolder.isLayoutRtl()) {
-            sTempPosArray[0] = getCountX() - sTempPosArray[0] - 1;
-        }
-
-        // Convert this position to rank.
-        return Math.min(mAllocatedContentSize - 1,
-                sTempPosArray[1] * getCountX() + sTempPosArray[0]);
-    }
-
-    @Override
-    public boolean isFull() {
-        return getItemCount() >= mMaxNumItems;
-    }
-
-    @Override
-    public int getItemCount() {
-        return getShortcutsAndWidgets().getChildCount();
-    }
-
-    @Override
-    public void arrangeChildren(ArrayList<View> list, int itemCount) {
-        setupContentDimensions(itemCount);
-        removeAllViews();
-
-        int newX, newY;
-        int rank = 0;
-        int countX = getCountX();
-        for (View v : list) {
-            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
-            newX = rank % countX;
-            newY = rank / countX;
-            ItemInfo info = (ItemInfo) v.getTag();
-            if (info.cellX != newX || info.cellY != newY || info.rank != rank) {
-                info.cellX = newX;
-                info.cellY = newY;
-                info.rank = rank;
-                LauncherModel.addOrMoveItemInDatabase(getContext(), info,
-                        mFolder.mInfo.id, 0, info.cellX, info.cellY);
-            }
-            lp.cellX = info.cellX;
-            lp.cellY = info.cellY;
-            rank ++;
-            addViewToCellLayout(v, -1, mFolder.mLauncher.getViewIdForItem(info), lp, true);
-        }
-    }
-
-    @Override
-    public View iterateOverItems(ItemOperator op) {
-        for (int j = 0; j < getCountY(); j++) {
-            for (int i = 0; i < getCountX(); i++) {
-                View v = getChildAt(i, j);
-                if ((v != null) && op.evaluate((ItemInfo) v.getTag(), v, this)) {
-                    return v;
-                }
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public String getAccessibilityDescription() {
-        return String.format(getContext().getString(R.string.folder_opened),
-                getCountX(), getCountY());
-    }
-
-    @Override
-    public void setFocusOnFirstChild() {
-        View firstChild = getChildAt(0, 0);
-        if (firstChild != null) {
-            firstChild.requestFocus();
-        }
-    }
-
-    @Override
-    public View getLastItem() {
-        int lastRank = getShortcutsAndWidgets().getChildCount() - 1;
-        // count can be zero if the folder is not yet laid out.
-        int count = getCountX();
-        if (count > 0) {
-            return getShortcutsAndWidgets().getChildAt(lastRank % count, lastRank / count);
-        } else {
-            return getShortcutsAndWidgets().getChildAt(lastRank);
-        }
-    }
-
-    @Override
-    public void realTimeReorder(int empty, int target) {
-        boolean wrap;
-        int startX;
-        int endX;
-        int startY;
-        int delay = 0;
-        float delayAmount = START_VIEW_REORDER_DELAY;
-
-        int countX = getCountX();
-        int emptyX = empty % getCountX();
-        int emptyY = empty / countX;
-
-        int targetX = target % countX;
-        int targetY = target / countX;
-
-        if (target > empty) {
-            wrap = emptyX == countX - 1;
-            startY = wrap ? emptyY + 1 : emptyY;
-            for (int y = startY; y <= targetY; y++) {
-                startX = y == emptyY ? emptyX + 1 : 0;
-                endX = y < targetY ? countX - 1 : targetX;
-                for (int x = startX; x <= endX; x++) {
-                    View v = getChildAt(x,y);
-                    if (animateChildToPosition(v, emptyX, emptyY,
-                            REORDER_ANIMATION_DURATION, delay, true, true)) {
-                        emptyX = x;
-                        emptyY = y;
-                        delay += delayAmount;
-                        delayAmount *= VIEW_REORDER_DELAY_FACTOR;
-                    }
-                }
-            }
-        } else {
-            wrap = emptyX == 0;
-            startY = wrap ? emptyY - 1 : emptyY;
-            for (int y = startY; y >= targetY; y--) {
-                startX = y == emptyY ? emptyX - 1 : countX - 1;
-                endX = y > targetY ? 0 : targetX;
-                for (int x = startX; x >= endX; x--) {
-                    View v = getChildAt(x,y);
-                    if (animateChildToPosition(v, emptyX, emptyY,
-                            REORDER_ANIMATION_DURATION, delay, true, true)) {
-                        emptyX = x;
-                        emptyY = y;
-                        delay += delayAmount;
-                        delayAmount *= VIEW_REORDER_DELAY_FACTOR;
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/src/com/android/launcher3/FolderPagedView.java b/src/com/android/launcher3/FolderPagedView.java
index 1c42d25..247c552 100644
--- a/src/com/android/launcher3/FolderPagedView.java
+++ b/src/com/android/launcher3/FolderPagedView.java
@@ -19,7 +19,6 @@
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.util.AttributeSet;
-import android.util.LayoutDirection;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -42,10 +41,15 @@
 import java.util.Iterator;
 import java.util.Map;
 
-public class FolderPagedView extends PagedView implements Folder.FolderContent {
+public class FolderPagedView extends PagedView {
 
     private static final String TAG = "FolderPagedView";
 
+    private static final boolean ALLOW_FOLDER_SCROLL = true;
+
+    // To enable this flag, user_folder.xml needs to be modified to add sort button.
+    private static final boolean ALLOW_ITEM_SORTING = false;
+
     private static final int REORDER_ANIMATION_DURATION = 230;
     private static final int START_VIEW_REORDER_DELAY = 30;
     private static final float VIEW_REORDER_DELAY_FACTOR = 0.9f;
@@ -96,32 +100,38 @@
         setDataIsReady();
 
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-        mMaxCountX = Math.min((int) grid.numColumns, MAX_ITEMS_PER_PAGE);
-        mMaxCountY = Math.min((int) grid.numRows, MAX_ITEMS_PER_PAGE);
+        if (ALLOW_FOLDER_SCROLL) {
+            mMaxCountX = Math.min((int) grid.numColumns, MAX_ITEMS_PER_PAGE);
+            mMaxCountY = Math.min((int) grid.numRows, MAX_ITEMS_PER_PAGE);
+        } else {
+            mMaxCountX = (int) grid.numColumns;
+            mMaxCountY = (int) grid.numRows;
+        }
+
         mMaxItemsPerPage = mMaxCountX * mMaxCountY;
 
         mInflater = LayoutInflater.from(context);
         mIconCache = app.getIconCache();
 
-        rtlLayout = getResources().getConfiguration().getLayoutDirection() == LayoutDirection.RTL;
+        rtlLayout = getResources().getConfiguration().getLayoutDirection() == LAYOUT_DIRECTION_RTL;
     }
 
-    @Override
     public void setFolder(Folder folder) {
         mFolder = folder;
         mFocusIndicatorView = (FocusIndicatorView) folder.findViewById(R.id.focus_indicator);
         mKeyListener = new PagedFolderKeyEventListener(folder);
-
-        mSortButton = folder.findViewById(R.id.folder_sort);
-        mSortButton.setOnClickListener(new OnClickListener() {
-
-            @Override
-            public void onClick(View v) {
-                onSortClicked();
-            }
-        });
         mPageIndicator = folder.findViewById(R.id.folder_page_indicator);
-        mSortSwitch = (Switch) folder.findViewById(R.id.folder_sort_switch);
+
+        if (ALLOW_ITEM_SORTING) {
+            // Initialize {@link #mSortSwitch} and {@link #mSortButton}.
+            mSortButton.setOnClickListener(new OnClickListener() {
+
+                @Override
+                public void onClick(View v) {
+                    onSortClicked();
+                }
+            });
+        }
     }
 
     private void onSortClicked() {
@@ -138,9 +148,11 @@
 
     private void setIsSorted(boolean isSorted, boolean saveChanges) {
         mIsSorted = isSorted;
-        mSortSwitch.setChecked(isSorted);
-        mFolder.mInfo.setOption(FolderInfo.FLAG_ITEMS_SORTED, isSorted,
-                saveChanges ? mFolder.mLauncher : null);
+        if (ALLOW_ITEM_SORTING) {
+            mSortSwitch.setChecked(isSorted);
+            mFolder.mInfo.setOption(FolderInfo.FLAG_ITEMS_SORTED, isSorted,
+                    saveChanges ? mFolder.mLauncher : null);
+        }
     }
 
     /**
@@ -282,26 +294,34 @@
         }
     }
 
-    @Override
+    /**
+     * Binds items to the layout.
+     * @return list of items that could not be bound, probably because we hit the max size limit.
+     */
     public ArrayList<ShortcutInfo> bindItems(ArrayList<ShortcutInfo> items) {
-        mIsSorted = mFolder.mInfo.hasOption(FolderInfo.FLAG_ITEMS_SORTED);
+        mIsSorted = ALLOW_ITEM_SORTING && mFolder.mInfo.hasOption(FolderInfo.FLAG_ITEMS_SORTED);
         ArrayList<View> icons = new ArrayList<View>();
+        ArrayList<ShortcutInfo> extra = new ArrayList<ShortcutInfo>();
+
         for (ShortcutInfo item : items) {
-            icons.add(createNewView(item));
+            if (!ALLOW_FOLDER_SCROLL && icons.size() >= mMaxItemsPerPage) {
+                extra.add(item);
+            } else {
+                icons.add(createNewView(item));
+            }
         }
         arrangeChildren(icons, icons.size(), false);
-        return new ArrayList<ShortcutInfo>();
+        return extra;
     }
 
     /**
      * Create space for a new item at the end, and returns the rank for that item.
      * Also sets the current page to the last page.
      */
-    @Override
     public int allocateRankForNewItem(ShortcutInfo info) {
         int rank = getItemCount();
         ArrayList<View> views = new ArrayList<View>(mFolder.getItemsInReadingOrder());
-        if (mIsSorted) {
+        if (ALLOW_ITEM_SORTING && mIsSorted) {
             View tmp = new View(getContext());
             tmp.setTag(info);
             int index = Collections.binarySearch(views, tmp, new ViewComparator());
@@ -321,14 +341,16 @@
         return rank;
     }
 
-    @Override
     public View createAndAddViewForRank(ShortcutInfo item, int rank) {
         View icon = createNewView(item);
         addViewForRank(icon, item, rank);
         return icon;
     }
 
-    @Override
+    /**
+     * Adds the {@param view} to the layout based on {@param rank} and updated the position
+     * related attributes. It assumes that {@param item} is already attached to the view.
+     */
     public void addViewForRank(View view, ShortcutInfo item, int rank) {
         int pagePos = rank % mMaxItemsPerPage;
         int pageNo = rank / mMaxItemsPerPage;
@@ -388,14 +410,12 @@
         return page;
     }
 
-    @Override
     public void setFixedSize(int width, int height) {
         for (int i = getChildCount() - 1; i >= 0; i --) {
             ((CellLayout) getChildAt(i)).setFixedSize(width, height);
         }
     }
 
-    @Override
     public void removeItem(View v) {
         for (int i = getChildCount() - 1; i >= 0; i --) {
             getPageAt(i).removeView(v);
@@ -412,7 +432,6 @@
      * at the end, otherwise it is ignored.
      *
      */
-    @Override
     public void arrangeChildren(ArrayList<View> list, int itemCount) {
         arrangeChildren(list, itemCount, true);
     }
@@ -488,19 +507,26 @@
             setCurrentPage(0);
         }
 
-        setIsSorted(isSorted, saveChanges);
+        setEnableOverscroll(getPageCount() > 1);
 
         // Update footer
-        if (getPageCount() > 1) {
-            mPageIndicator.setVisibility(View.VISIBLE);
-            mSortButton.setVisibility(View.VISIBLE);
-            mFolder.mFolderName.setGravity(rtlLayout ? Gravity.RIGHT : Gravity.LEFT);
-            setEnableOverscroll(true);
+        if (ALLOW_ITEM_SORTING) {
+            setIsSorted(isSorted, saveChanges);
+            if (getPageCount() > 1) {
+                mPageIndicator.setVisibility(View.VISIBLE);
+                mSortButton.setVisibility(View.VISIBLE);
+                mFolder.mFolderName.setGravity(rtlLayout ? Gravity.RIGHT : Gravity.LEFT);
+            } else {
+                mPageIndicator.setVisibility(View.GONE);
+                mSortButton.setVisibility(View.GONE);
+                mFolder.mFolderName.setGravity(Gravity.CENTER_HORIZONTAL);
+            }
         } else {
-            mPageIndicator.setVisibility(View.GONE);
-            mSortButton.setVisibility(View.GONE);
-            mFolder.mFolderName.setGravity(Gravity.CENTER_HORIZONTAL);
-            setEnableOverscroll(false);
+            int indicatorVisibility = mPageIndicator.getVisibility();
+            mPageIndicator.setVisibility(getPageCount() > 1 ? View.VISIBLE : View.GONE);
+            if (indicatorVisibility != mPageIndicator.getVisibility()) {
+                mFolder.updateFooterHeight();
+            }
         }
     }
 
@@ -521,7 +547,6 @@
         return  getPageCount() > 0 ? getPageAt(0).getDesiredHeight() : 0;
     }
 
-    @Override
     public int getItemCount() {
         int lastPageIndex = getChildCount() - 1;
         if (lastPageIndex < 0) {
@@ -532,7 +557,9 @@
                 + lastPageIndex * mMaxItemsPerPage;
     }
 
-    @Override
+    /**
+     * @return the rank of the cell nearest to the provided pixel position.
+     */
     public int findNearestArea(int pixelX, int pixelY) {
         int pageIndex = getNextPage();
         CellLayout page = getPageAt(pageIndex);
@@ -550,12 +577,10 @@
                 R.drawable.ic_pageindicator_default_folder);
     }
 
-    @Override
     public boolean isFull() {
-        return false;
+        return !ALLOW_FOLDER_SCROLL && getItemCount() >= mMaxItemsPerPage;
     }
 
-    @Override
     public View getLastItem() {
         if (getChildCount() < 1) {
             return null;
@@ -569,7 +594,10 @@
         }
     }
 
-    @Override
+    /**
+     * Iterates over all its items in a reading order.
+     * @return the view for which the operator returned true.
+     */
     public View iterateOverItems(ItemOperator op) {
         for (int k = 0 ; k < getChildCount(); k++) {
             CellLayout page = getPageAt(k);
@@ -585,13 +613,14 @@
         return null;
     }
 
-    @Override
     public String getAccessibilityDescription() {
         return String.format(getContext().getString(R.string.folder_opened),
                 mGridCountX, mGridCountY);
     }
 
-    @Override
+    /**
+     * Sets the focus on the first visible child.
+     */
     public void setFocusOnFirstChild() {
         View firstChild = getCurrentCellLayout().getChildAt(0, 0);
         if (firstChild != null) {
@@ -605,7 +634,7 @@
         if (mFolder != null) {
             mFolder.updateTextViewFocus();
         }
-        if (mSortOperationPending && getNextPage() == 0) {
+        if (ALLOW_ITEM_SORTING && mSortOperationPending && getNextPage() == 0) {
             post(new Runnable() {
 
                 @Override
@@ -680,7 +709,9 @@
         }
     }
 
-    @Override
+    /**
+     * Reorders the items such that the {@param empty} spot moves to {@param target}
+     */
     public void realTimeReorder(int empty, int target) {
         completePendingPageChanges();
         int delay = 0;