Merge "WidgetTray UI improvement" into ub-launcher3-burnaby
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f43106f..b61b90c 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -192,15 +192,6 @@
             </intent-filter>
         </receiver>
 
-        <!-- New user initialization; set up initial wallpaper -->
-        <receiver
-            android:name="com.android.launcher3.UserInitializeReceiver"
-            android:exported="false">
-            <intent-filter>
-                <action android:name="android.intent.action.USER_INITIALIZE" />
-            </intent-filter>
-        </receiver>
-
         <receiver android:name="com.android.launcher3.StartupReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
diff --git a/res/drawable/apps_list_bg.xml b/res/drawable/apps_list_bg.xml
index 64177c1..0e56684 100644
--- a/res/drawable/apps_list_bg.xml
+++ b/res/drawable/apps_list_bg.xml
@@ -14,7 +14,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-       android:drawable="@drawable/apps_list_bg_inset"
-       android:insetLeft="@dimen/apps_container_inset"
-       android:insetRight="@dimen/apps_container_inset" />
\ No newline at end of file
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <solid android:color="#ffffff" />
+    <corners
+        android:radius="2dp" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/apps_list_search_bg.xml b/res/drawable/apps_list_search_bg.xml
index eda33a9..63c4d55 100644
--- a/res/drawable/apps_list_search_bg.xml
+++ b/res/drawable/apps_list_search_bg.xml
@@ -18,6 +18,6 @@
        android:shape="rectangle">
     <solid android:color="#ffffff" />
     <corners
-        android:topLeftRadius="3dp"
-        android:topRightRadius="3dp" />
+        android:bottomLeftRadius="2dp"
+        android:bottomRightRadius="2dp" />
 </shape>
\ No newline at end of file
diff --git a/res/drawable/apps_reveal_bg.xml b/res/drawable/apps_reveal_bg.xml
index 47c608f..07505a5 100644
--- a/res/drawable/apps_reveal_bg.xml
+++ b/res/drawable/apps_reveal_bg.xml
@@ -14,7 +14,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-       android:drawable="@drawable/apps_reveal_bg_inset"
-       android:insetLeft="@dimen/apps_container_inset"
-       android:insetRight="@dimen/apps_container_inset" />
\ No newline at end of file
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <solid android:color="#ffffff" />
+    <corners android:radius="2dp" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/apps_reveal_bg_inset.xml b/res/drawable/apps_reveal_bg_inset.xml
deleted file mode 100644
index 61f1c08..0000000
--- a/res/drawable/apps_reveal_bg_inset.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="rectangle">
-    <solid android:color="#ffffff" />
-    <corners android:radius="3dp" />
-</shape>
\ No newline at end of file
diff --git a/res/drawable/apps_list_bg_inset.xml b/res/drawable/apps_search_bg.xml
similarity index 90%
rename from res/drawable/apps_list_bg_inset.xml
rename to res/drawable/apps_search_bg.xml
index 5ea7895..405e844 100644
--- a/res/drawable/apps_list_bg_inset.xml
+++ b/res/drawable/apps_search_bg.xml
@@ -18,6 +18,6 @@
        android:shape="rectangle">
     <solid android:color="#ffffff" />
     <corners
-        android:bottomLeftRadius="3dp"
-        android:bottomRightRadius="3dp" />
+        android:topLeftRadius="2dp"
+        android:topRightRadius="2dp" />
 </shape>
\ No newline at end of file
diff --git a/res/layout-sw600dp/apps_view.xml b/res/layout-sw600dp/apps_view.xml
index fba170b..e6e0ec3 100644
--- a/res/layout-sw600dp/apps_view.xml
+++ b/res/layout-sw600dp/apps_view.xml
@@ -19,7 +19,6 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:padding="@dimen/apps_container_inset"
-    android:background="@drawable/apps_customize_bg"
     android:descendantFocusability="afterDescendants">
     <include
         layout="@layout/apps_reveal_view"
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 8bd827a..a9601af 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -67,7 +67,7 @@
             android:layout_gravity="center_horizontal" />
 
         <include layout="@layout/widgets_view"
-            android:id="@+id/widget_view"
+            android:id="@+id/widgets_view"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:visibility="invisible" />
diff --git a/res/layout/apps_list_view.xml b/res/layout/apps_list_view.xml
index 3e42f84..595c46c 100644
--- a/res/layout/apps_list_view.xml
+++ b/res/layout/apps_list_view.xml
@@ -25,8 +25,6 @@
         android:id="@+id/app_search_box"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="@dimen/apps_container_inset"
-        android:layout_marginRight="@dimen/apps_container_inset"
         android:padding="16dp"
         android:hint="@string/apps_view_search_bar_hint"
         android:maxLines="1"
@@ -37,7 +35,7 @@
         android:textColor="#4c4c4c"
         android:textColorHint="#9c9c9c"
         android:imeOptions="actionDone|flagNoExtractUi"
-        android:background="@drawable/apps_list_search_bg"
+        android:background="@drawable/apps_search_bg"
         android:elevation="4dp" />
     <com.android.launcher3.AppsContainerRecyclerView
         android:id="@+id/apps_list_view"
@@ -48,6 +46,5 @@
         android:paddingBottom="12dp"
         android:clipToPadding="false"
         android:focusable="true"
-        android:descendantFocusability="afterDescendants"
-        android:background="@drawable/apps_list_bg" />
+        android:descendantFocusability="afterDescendants" />
 </LinearLayout>
\ No newline at end of file
diff --git a/res/layout/apps_reveal_view.xml b/res/layout/apps_reveal_view.xml
index bc93359..2951ea4 100644
--- a/res/layout/apps_reveal_view.xml
+++ b/res/layout/apps_reveal_view.xml
@@ -21,5 +21,4 @@
     android:layout_gravity="center"
     android:elevation="15dp"
     android:visibility="invisible"
-    android:background="@drawable/apps_reveal_bg"
     android:focusable="false" />
\ No newline at end of file
diff --git a/res/layout/apps_view.xml b/res/layout/apps_view.xml
index 86d67e1..7f09f77 100644
--- a/res/layout/apps_view.xml
+++ b/res/layout/apps_view.xml
@@ -21,9 +21,6 @@
     android:id="@+id/apps_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:paddingTop="@dimen/apps_container_inset"
-    android:paddingBottom="@dimen/apps_container_inset"
-    android:background="@drawable/apps_customize_bg"
     android:descendantFocusability="afterDescendants">
     <include
         layout="@layout/apps_reveal_view"
diff --git a/res/layout/page_indicator_marker.xml b/res/layout/page_indicator_marker.xml
index 686d275..564a958 100644
--- a/res/layout/page_indicator_marker.xml
+++ b/res/layout/page_indicator_marker.xml
@@ -16,8 +16,8 @@
 <com.android.launcher3.PageIndicatorMarker
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:launcher="http://schemas.android.com/apk/res-auto"
-    android:layout_width="16dp"
-    android:layout_height="16dp"
+    android:layout_width="12dp"
+    android:layout_height="12dp"
     android:layout_gravity="center_vertical">
     <ImageView
         android:id="@+id/inactive"
diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml
index 7a4d5e8..cd3a051 100644
--- a/res/layout/user_folder.xml
+++ b/res/layout/user_folder.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-     Copyright (C) 2008 The Android Open Source Project
+     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.
@@ -34,30 +34,44 @@
             android:layout_width="20dp"
             android:layout_height="20dp" />
 
-        <com.android.launcher3.FolderCellLayout
+        <com.android.launcher3.FolderPagedView
             android:id="@+id/folder_content"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:cacheColorHint="#ff333333"
-            android:hapticFeedbackEnabled="false" />
+            launcher:pageIndicator="@+id/folder_page_indicator" />
     </FrameLayout>
 
-    <com.android.launcher3.FolderEditText
-        android:id="@+id/folder_name"
+    <LinearLayout
+        android:id="@+id/folder_footer"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:background="#00000000"
-        android:fontFamily="sans-serif-condensed"
-        android:gravity="center_horizontal"
-        android:hint="@string/folder_hint_text"
-        android:imeOptions="flagNoExtractUi"
-        android:paddingBottom="@dimen/folder_name_padding"
-        android:paddingTop="@dimen/folder_name_padding"
-        android:singleLine="true"
-        android:textColor="#ff777777"
-        android:textColorHighlight="#ffCCCCCC"
-        android:textColorHint="#ff808080"
-        android:textCursorDrawable="@null"
-        android:textSize="14sp" />
+        android:orientation="vertical" >
+
+        <include
+            android:id="@+id/folder_page_indicator"
+            android:layout_width="wrap_content"
+            android:layout_height="12dp"
+            android:layout_gravity="center_horizontal"
+            layout="@layout/page_indicator" />
+
+        <com.android.launcher3.FolderEditText
+            android:id="@+id/folder_name"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:background="#00000000"
+            android:fontFamily="sans-serif-condensed"
+            android:gravity="center_horizontal"
+            android:hint="@string/folder_hint_text"
+            android:imeOptions="flagNoExtractUi"
+            android:paddingBottom="@dimen/folder_name_padding"
+            android:paddingTop="@dimen/folder_name_padding"
+            android:singleLine="true"
+            android:textColor="#ff777777"
+            android:textColorHighlight="#ffCCCCCC"
+            android:textColorHint="#ff808080"
+            android:textCursorDrawable="@null"
+            android:textSize="14sp" />
+    </LinearLayout>
 
 </com.android.launcher3.Folder>
\ No newline at end of file
diff --git a/res/layout/user_folder_scroll.xml b/res/layout/user_folder_scroll.xml
deleted file mode 100644
index 12e5097..0000000
--- a/res/layout/user_folder_scroll.xml
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-
-<com.android.launcher3.Folder xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:background="@drawable/quantum_panel"
-    android:orientation="vertical" >
-
-    <FrameLayout
-        android:id="@+id/folder_content_wrapper"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" >
-
-        <!-- Actual size of the indicator doesn't matter as it is scaled to match the view size -->
-
-        <com.android.launcher3.FocusIndicatorView
-            android:id="@+id/focus_indicator"
-            android:layout_width="20dp"
-            android:layout_height="20dp" />
-
-        <com.android.launcher3.FolderPagedView
-            android:id="@+id/folder_content"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            launcher:pageIndicator="@+id/folder_page_indicator" />
-    </FrameLayout>
-
-    <LinearLayout
-        android:id="@+id/folder_footer"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal"
-        android:paddingStart="12dp"
-        android:paddingEnd="8dp" >
-
-        <com.android.launcher3.FolderEditText
-            android:id="@+id/folder_name"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_vertical"
-            android:layout_weight="1"
-            android:background="#00000000"
-            android:fontFamily="sans-serif-condensed"
-            android:gravity="start"
-            android:hint="@string/folder_hint_text"
-            android:imeOptions="flagNoExtractUi"
-            android:paddingBottom="@dimen/folder_name_padding"
-            android:paddingTop="@dimen/folder_name_padding"
-            android:singleLine="true"
-            android:textColor="#ff777777"
-            android:textColorHighlight="#ffCCCCCC"
-            android:textColorHint="#ff808080"
-            android:textCursorDrawable="@null"
-            android:textSize="14sp" />
-
-        <include
-            android:id="@+id/folder_page_indicator"
-            android:layout_width="wrap_content"
-            android:layout_height="12dp"
-            android:layout_gravity="top"
-            android:layout_marginTop="5dp"
-            layout="@layout/page_indicator" />
-
-        <LinearLayout
-            android:id="@+id/folder_sort"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:layout_gravity="center_vertical"
-            android:gravity="end|center_vertical" >
-
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginEnd="8dp"
-                android:text="@string/sort_alphabetical"
-                android:textColor="#ff777777"
-                android:textSize="14sp" />
-
-            <Switch
-                android:id="@+id/folder_sort_switch"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:clickable="false"
-                android:duplicateParentState="true"
-                android:focusable="false" />
-        </LinearLayout>
-    </LinearLayout>
-
-</com.android.launcher3.Folder>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 7c99278..101b755 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -50,6 +50,8 @@
     <dimen name="apps_container_width">0dp</dimen>
     <dimen name="apps_container_height">0dp</dimen>
     <dimen name="apps_container_inset">8dp</dimen>
+    <!-- Note: This needs to match the fixed insets for the search box -->
+    <dimen name="apps_container_fixed_bounds_inset">8dp</dimen>
     <dimen name="apps_grid_view_start_margin">52dp</dimen>
     <dimen name="apps_view_row_height">64dp</dimen>
     <dimen name="apps_view_section_text_size">24sp</dimen>
diff --git a/src/com/android/launcher3/AppsContainerRecyclerView.java b/src/com/android/launcher3/AppsContainerRecyclerView.java
index c93bacf..bb2aeb0 100644
--- a/src/com/android/launcher3/AppsContainerRecyclerView.java
+++ b/src/com/android/launcher3/AppsContainerRecyclerView.java
@@ -196,13 +196,27 @@
                 }
                 break;
             case MotionEvent.ACTION_UP:
+                ViewConfiguration viewConfig = ViewConfiguration.get(getContext());
+                float dx = ev.getX() - mDownX;
+                float dy = ev.getY() - mDownY;
+                float distance = (float) Math.sqrt(dx * dx + dy * dy);
+                if (distance < viewConfig.getScaledTouchSlop()) {
+                    Rect backgroundPadding = new Rect();
+                    getBackground().getPadding(backgroundPadding);
+                    boolean isOutsideBounds = ev.getX() < backgroundPadding.left ||
+                            ev.getX() > (getWidth() - backgroundPadding.right);
+                    if (isOutsideBounds) {
+                        Launcher launcher = (Launcher) getContext();
+                        launcher.showWorkspace(true);
+                    }
+                }
+                // Fall through
             case MotionEvent.ACTION_CANCEL:
                 mDraggingFastScroller = false;
                 animateFastScrollerVisibility(false);
                 break;
         }
         return mDraggingFastScroller;
-
     }
 
     /**
diff --git a/src/com/android/launcher3/AppsContainerView.java b/src/com/android/launcher3/AppsContainerView.java
index 2de45cb..559f6eb 100644
--- a/src/com/android/launcher3/AppsContainerView.java
+++ b/src/com/android/launcher3/AppsContainerView.java
@@ -19,6 +19,7 @@
 import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.graphics.drawable.InsetDrawable;
 import android.support.v7.widget.RecyclerView;
 import android.text.Editable;
 import android.text.TextWatcher;
@@ -26,12 +27,13 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.EditText;
 import android.widget.FrameLayout;
+import android.widget.LinearLayout;
 import android.widget.TextView;
-
 import com.android.launcher3.util.Thunk;
 
 import java.util.List;
@@ -59,8 +61,13 @@
     private EditText mSearchBar;
     private int mNumAppsPerRow;
     private Point mLastTouchDownPos = new Point();
-    private Rect mPadding = new Rect();
+    private Rect mInsets = new Rect();
+    private Rect mFixedBounds = new Rect();
     private int mContentMarginStart;
+    // Normal container insets
+    private int mContainerInset;
+    // Fixed bounds container insets
+    private int mFixedBoundsContainerInset;
 
     public AppsContainerView(Context context) {
         this(context, null);
@@ -76,6 +83,10 @@
         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
         Resources res = context.getResources();
 
+        mContainerInset = context.getResources().getDimensionPixelSize(
+                R.dimen.apps_container_inset);
+        mFixedBoundsContainerInset = context.getResources().getDimensionPixelSize(
+                R.dimen.apps_container_fixed_bounds_inset);
         mLauncher = (Launcher) context;
         mApps = new AlphabeticalAppsList(context);
         if (USE_LAYOUT == GRID_LAYOUT) {
@@ -126,6 +137,15 @@
     }
 
     /**
+     * Hides the search bar
+     */
+    public void hideSearchBar() {
+        mSearchBar.setVisibility(View.GONE);
+        updateBackgrounds();
+        updatePaddings();
+    }
+
+    /**
      * Scrolls this list view to the top.
      */
     public void scrollToTop() {
@@ -154,45 +174,58 @@
             ((AppsGridAdapter) mAdapter).setRtl(isRtl);
         }
         mSearchBar = (EditText) findViewById(R.id.app_search_box);
-        mSearchBar.addTextChangedListener(this);
-        mSearchBar.setOnEditorActionListener(this);
+        if (mSearchBar != null) {
+            mSearchBar.addTextChangedListener(this);
+            mSearchBar.setOnEditorActionListener(this);
+        }
         mAppsListView = (AppsContainerRecyclerView) findViewById(R.id.apps_list_view);
         mAppsListView.setApps(mApps);
         mAppsListView.setNumAppsPerRow(mNumAppsPerRow);
         mAppsListView.setLayoutManager(mLayoutManager);
         mAppsListView.setAdapter(mAdapter);
         mAppsListView.setHasFixedSize(true);
-        if (isRtl) {
-            mAppsListView.setPadding(
-                    mAppsListView.getPaddingLeft(),
-                    mAppsListView.getPaddingTop(),
-                    mAppsListView.getPaddingRight() + mContentMarginStart,
-                    mAppsListView.getPaddingBottom());
-        } else {
-            mAppsListView.setPadding(
-                    mAppsListView.getPaddingLeft() + mContentMarginStart,
-                    mAppsListView.getPaddingTop(),
-                    mAppsListView.getPaddingRight(),
-                    mAppsListView.getPaddingBottom());
-        }
         if (mItemDecoration != null) {
             mAppsListView.addItemDecoration(mItemDecoration);
         }
-        mPadding.set(getPaddingLeft(), getPaddingTop(), getPaddingRight(),
-                getPaddingBottom());
+        updateBackgrounds();
+        updatePaddings();
     }
 
     @Override
     public void setInsets(Rect insets) {
-        setPadding(mPadding.left + insets.left, mPadding.top + insets.top,
-                mPadding.right + insets.right, mPadding.bottom + insets.bottom);
+        mInsets.set(insets);
+        updatePaddings();
+    }
+
+    /**
+     * Sets the fixed bounds for this Apps view.
+     */
+    public void setFixedBounds(Context context, Rect fixedBounds) {
+        if (!fixedBounds.isEmpty() && !fixedBounds.equals(mFixedBounds)) {
+            // Update the number of items in the grid
+            LauncherAppState app = LauncherAppState.getInstance();
+            DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+            if (grid.updateAppsViewNumCols(context.getResources(), fixedBounds.width())) {
+                mNumAppsPerRow = grid.appsViewNumCols;
+                mAppsListView.setNumAppsPerRow(mNumAppsPerRow);
+                if (USE_LAYOUT == GRID_LAYOUT) {
+                    ((AppsGridAdapter) mAdapter).setNumAppsPerRow(mNumAppsPerRow);
+                }
+            }
+
+            mFixedBounds.set(fixedBounds);
+        }
+        updateBackgrounds();
+        updatePaddings();
     }
 
     @Override
     public boolean onTouch(View v, MotionEvent ev) {
-        if (ev.getAction() == MotionEvent.ACTION_DOWN ||
-                ev.getAction() == MotionEvent.ACTION_MOVE) {
-            mLastTouchDownPos.set((int) ev.getX(), (int) ev.getY());
+        switch (ev.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+            case MotionEvent.ACTION_MOVE:
+                mLastTouchDownPos.set((int) ev.getX(), (int) ev.getY());
+                break;
         }
         return false;
     }
@@ -359,7 +392,9 @@
     public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
         if (!toWorkspace) {
             // Disable the focus so that the search bar doesn't get focus
-            mSearchBar.setFocusableInTouchMode(false);
+            if (mSearchBar != null) {
+                mSearchBar.setFocusableInTouchMode(false);
+            }
         }
     }
 
@@ -375,11 +410,69 @@
 
     @Override
     public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
-        if (toWorkspace) {
-            // Clear the search bar
-            mSearchBar.setText("");
-        } else {
-            mSearchBar.setFocusableInTouchMode(true);
+        if (mSearchBar != null) {
+            if (toWorkspace) {
+                // Clear the search bar
+                mSearchBar.setText("");
+            } else {
+                mSearchBar.setFocusableInTouchMode(true);
+            }
         }
     }
+
+    /**
+     * Update the padding of the Apps view and children.  To ensure that the RecyclerView has the
+     * full width to handle touches right to the edge of the screen, we only apply the top and
+     * bottom padding to the AppsContainerView and then the left/right padding on the RecyclerView
+     * itself.  In particular, the left/right padding is applied to the background of the view,
+     * and then additionally inset by the start margin.
+     */
+    private void updatePaddings() {
+        boolean isRtl = (getResources().getConfiguration().getLayoutDirection() ==
+                LAYOUT_DIRECTION_RTL);
+        boolean hasSearchBar = (mSearchBar != null) && (mSearchBar.getVisibility() == View.VISIBLE);
+
+        if (mFixedBounds.isEmpty()) {
+            // If there are no fixed bounds, then use the default padding and insets
+            setPadding(mInsets.left, mContainerInset + mInsets.top, mInsets.right,
+                    mContainerInset + mInsets.bottom);
+        } else {
+            // If there are fixed bounds, then we update the padding to reflect the fixed bounds.
+            setPadding(mFixedBounds.left, mFixedBounds.top + mFixedBoundsContainerInset,
+                    getMeasuredWidth() - mFixedBounds.right,
+                    mInsets.bottom + mFixedBoundsContainerInset);
+        }
+
+        // Update the apps recycler view
+        int inset = mFixedBounds.isEmpty() ? mContainerInset : mFixedBoundsContainerInset;
+        if (isRtl) {
+            mAppsListView.setPadding(inset, inset, inset + mContentMarginStart, inset);
+        } else {
+            mAppsListView.setPadding(inset + mContentMarginStart, inset, inset, inset);
+        }
+
+        // Update the search bar
+        if (hasSearchBar) {
+            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSearchBar.getLayoutParams();
+            lp.leftMargin = lp.rightMargin = inset;
+        }
+    }
+
+    /**
+     * Update the background of the Apps view and children.
+     */
+    private void updateBackgrounds() {
+        int inset = mFixedBounds.isEmpty() ? mContainerInset : mFixedBoundsContainerInset;
+        boolean hasSearchBar = (mSearchBar != null) && (mSearchBar.getVisibility() == View.VISIBLE);
+
+        // Update the background of the reveal view and list to be inset with the fixed bound
+        // insets instead of the default insets
+        mAppsListView.setBackground(new InsetDrawable(
+                getContext().getResources().getDrawable(
+                        hasSearchBar ? R.drawable.apps_list_search_bg : R.drawable.apps_list_bg),
+                inset, 0, inset, 0));
+        getRevealView().setBackground(new InsetDrawable(
+                getContext().getResources().getDrawable(R.drawable.apps_reveal_bg),
+                inset, 0, inset, 0));
+    }
 }
diff --git a/src/com/android/launcher3/AppsGridAdapter.java b/src/com/android/launcher3/AppsGridAdapter.java
index 5b6967c..c8ce397 100644
--- a/src/com/android/launcher3/AppsGridAdapter.java
+++ b/src/com/android/launcher3/AppsGridAdapter.java
@@ -112,6 +112,7 @@
 
     private LayoutInflater mLayoutInflater;
     @Thunk AlphabeticalAppsList mApps;
+    private GridLayoutManager mGridLayoutMgr;
     private GridSpanSizer mGridSizer;
     private GridItemDecoration mItemDecoration;
     private View.OnTouchListener mTouchListener;
@@ -135,6 +136,9 @@
         mApps = apps;
         mAppsPerRow = appsPerRow;
         mGridSizer = new GridSpanSizer();
+        mGridLayoutMgr = new GridLayoutManager(context, appsPerRow, GridLayoutManager.VERTICAL,
+                false);
+        mGridLayoutMgr.setSpanSizeLookup(mGridSizer);
         mItemDecoration = new GridItemDecoration();
         mLayoutInflater = LayoutInflater.from(context);
         mTouchListener = touchListener;
@@ -150,6 +154,14 @@
     }
 
     /**
+     * Sets the number of apps per row.
+     */
+    public void setNumAppsPerRow(int appsPerRow) {
+        mAppsPerRow = appsPerRow;
+        mGridLayoutMgr.setSpanCount(appsPerRow);
+    }
+
+    /**
      * Sets whether we are in RTL mode.
      */
     public void setRtl(boolean rtl) {
@@ -167,10 +179,7 @@
      * Returns the grid layout manager.
      */
     public GridLayoutManager getLayoutManager(Context context) {
-        GridLayoutManager layoutMgr = new GridLayoutManager(context, mAppsPerRow,
-                GridLayoutManager.VERTICAL, false);
-        layoutMgr.setSpanSizeLookup(mGridSizer);
-        return layoutMgr;
+        return mGridLayoutMgr;
     }
 
     /**
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index ea28520..786f2ce 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -423,13 +423,21 @@
             allAppsNumCols = Math.max(minEdgeCellCount, Math.min(maxCols, allAppsNumCols));
         }
 
-        int appsContainerViewPx = res.getDimensionPixelSize(R.dimen.apps_container_width);
+        int appsContainerViewWidthPx = res.getDimensionPixelSize(R.dimen.apps_container_width);
+        updateAppsViewNumCols(res, appsContainerViewWidthPx);
+    }
+
+    public boolean updateAppsViewNumCols(Resources res, int containerWidth) {
         int appsViewLeftMarginPx =
                 res.getDimensionPixelSize(R.dimen.apps_grid_view_start_margin);
-        int availableAppsWidthPx = (appsContainerViewPx > 0) ? appsContainerViewPx :
-                availableWidthPx;
-        appsViewNumCols = (availableAppsWidthPx - appsViewLeftMarginPx) /
+        int availableAppsWidthPx = (containerWidth > 0) ? containerWidth : availableWidthPx;
+        int numCols = (availableAppsWidthPx - appsViewLeftMarginPx) /
                 (allAppsCellWidthPx + 2 * allAppsCellPaddingPx);
+        if (numCols != appsViewNumCols) {
+            appsViewNumCols = numCols;
+            return true;
+        }
+        return false;
     }
 
     void updateFromConfiguration(Context context, Resources resources, int wPx, int hPx,
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;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 068934e..3d2a346 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -520,6 +520,17 @@
 
     public boolean setLauncherCallbacks(LauncherCallbacks callbacks) {
         mLauncherCallbacks = callbacks;
+        mLauncherCallbacks.setLauncherAppsCallback(new Launcher.LauncherAppsCallbacks() {
+            @Override
+            public void onAllAppsBoundsChanged(Rect bounds) {
+                mAppsView.setFixedBounds(Launcher.this, bounds);
+            }
+
+            @Override
+            public void dismissAllApps() {
+                showWorkspace(true);
+            }
+        });
         return true;
     }
 
@@ -1141,6 +1152,19 @@
         public void forceExitFullImmersion();
     }
 
+    public interface LauncherAppsCallbacks {
+        /**
+         * Updates launcher to the available space that AllApps can take so as not to overlap with
+         * any other views.
+         */
+        public void onAllAppsBoundsChanged(Rect bounds);
+
+        /**
+         * Called to dismiss all apps if it is showing.
+         */
+        public void dismissAllApps();
+    }
+
     public interface LauncherOverlayCallbacks {
         /**
          * This method indicates whether a call to {@link #enterFullImmersion()} will succeed,
@@ -1418,6 +1442,9 @@
 
         // Setup Apps
         mAppsView = (AppsContainerView) findViewById(R.id.apps_view);
+        if (mLauncherCallbacks != null && mLauncherCallbacks.overrideAllAppsSearch()) {
+            mAppsView.hideSearchBar();
+        }
 
         // Setup AppsCustomize
         mWidgetsView = (WidgetsContainerView) findViewById(R.id.widgets_view);
@@ -2587,9 +2614,6 @@
         } else {
             showAppsView(true /* animated */, false /* resetListToTop */);
         }
-        if (mLauncherCallbacks != null) {
-            mLauncherCallbacks.onClickAllAppsButton(v);
-        }
     }
 
     private void showBrokenAppInstallDialog(final String packageName,
@@ -3270,7 +3294,9 @@
     }
 
     void showWorkspace(boolean animated, Runnable onCompleteRunnable) {
-        if (mState != State.WORKSPACE || mWorkspace.getState() != Workspace.State.NORMAL) {
+        boolean changed = mState != State.WORKSPACE ||
+                mWorkspace.getState() != Workspace.State.NORMAL;
+        if (changed) {
             boolean wasInSpringLoadedMode = (mState != State.WORKSPACE);
             mWorkspace.setVisibility(View.VISIBLE);
             mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.NORMAL,
@@ -3295,11 +3321,13 @@
         mUserPresent = true;
         updateAutoAdvanceState();
 
-        // Send an accessibility event to announce the context change
-        getWindow().getDecorView()
-                .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+        if (changed) {
+            // Send an accessibility event to announce the context change
+            getWindow().getDecorView()
+                    .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
 
-        onWorkspaceShown(animated);
+            onWorkspaceShown(animated);
+        }
     }
 
     void showOverviewMode(boolean animated) {
@@ -3350,6 +3378,9 @@
 
         if (toState == State.APPS) {
             mStateTransitionAnimation.startAnimationToAllApps(animated);
+            if (mLauncherCallbacks != null) {
+                mLauncherCallbacks.onAllAppsShown();
+            }
         } else {
             mStateTransitionAnimation.startAnimationToWidgets(animated);
         }
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
index d8128d6..2fee81c 100644
--- a/src/com/android/launcher3/LauncherCallbacks.java
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -50,6 +50,7 @@
     public void onLauncherProviderChange();
     public void finishBindingItems(final boolean upgradePath);
     public void onClickAllAppsButton(View v);
+    public void onAllAppsShown();
     public void bindAllApplications(ArrayList<AppInfo> apps);
     public void onClickFolderIcon(View v);
     public void onClickAppShortcut(View v);
@@ -87,6 +88,7 @@
     public ComponentName getWallpaperPickerComponent();
     public boolean overrideWallpaperDimensions();
     public boolean isLauncherPreinstalled();
+    public boolean overrideAllAppsSearch();
 
     /**
      * Returning true will immediately result in a call to {@link #setLauncherOverlayView(ViewGroup,
@@ -106,4 +108,12 @@
     public Launcher.LauncherOverlay setLauncherOverlayView(InsettableFrameLayout container,
             Launcher.LauncherOverlayCallbacks callbacks);
 
+    /**
+     * Sets the callbacks to allow any extensions to callback to the launcher.
+     *
+     * @param callbacks A set of callbacks to the Launcher, is actually a LauncherAppsCallback, but
+     *                  for implementation purposes is passed around as an object.
+     */
+    public void setLauncherAppsCallback(Object callbacks);
+
 }
diff --git a/src/com/android/launcher3/LauncherExtension.java b/src/com/android/launcher3/LauncherExtension.java
index fe9bd6c..e4fdbbc 100644
--- a/src/com/android/launcher3/LauncherExtension.java
+++ b/src/com/android/launcher3/LauncherExtension.java
@@ -124,6 +124,10 @@
         }
 
         @Override
+        public void onAllAppsShown() {
+        }
+
+        @Override
         public void bindAllApplications(ArrayList<AppInfo> apps) {
         }
 
@@ -246,6 +250,11 @@
         }
 
         @Override
+        public boolean overrideAllAppsSearch() {
+            return false;
+        }
+
+        @Override
         public boolean isLauncherPreinstalled() {
             return false;
         }
@@ -265,6 +274,11 @@
             return mLauncherOverlay;
         }
 
+        @Override
+        public void setLauncherAppsCallback(Object callbacks) {
+            // Do nothing
+        }
+
         class LauncherExtensionOverlay implements LauncherOverlay {
             LauncherOverlayCallbacks mLauncherOverlayCallbacks;
             ViewGroup mOverlayView;
diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
index e92bfb0..57bd5b2 100644
--- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java
+++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
@@ -174,7 +174,7 @@
             }
         };
         startAnimationToOverlay(Workspace.State.NORMAL_HIDDEN, toView, toView.getContentView(),
-                toView.getRevealView(), null, animated, cb);
+                toView.getRevealView(), animated, false /* hideSearchBar */, cb);
     }
 
     /**
@@ -198,7 +198,7 @@
             }
         };
         startAnimationToOverlay(Workspace.State.OVERVIEW_HIDDEN, toView, toView.getContentView(),
-                toView.getRevealView(), null, animated, cb);
+                toView.getRevealView(), animated, true /* hideSearchBar */, cb);
     }
 
     /**
@@ -226,8 +226,8 @@
      * Creates and starts a new animation to a particular overlay view.
      */
     private void startAnimationToOverlay(final Workspace.State toWorkspaceState, final View toView,
-             final View contentView, final View revealView, final View pageIndicatorsView,
-             final boolean animated, final PrivateTransitionCallbacks pCb) {
+             final View contentView, final View revealView, final boolean animated,
+             final boolean hideSearchBar, final PrivateTransitionCallbacks pCb) {
         final Resources res = mLauncher.getResources();
         final boolean material = Utilities.isLmpOrAbove();
         final int revealDuration = res.getInteger(R.integer.config_appsCustomizeRevealTime);
@@ -293,15 +293,6 @@
             layerViews.put(revealView, BUILD_AND_SET_LAYER);
             mStateAnimation.play(panelAlphaAndDrift);
 
-            // Setup the animation for the page indicators
-            if (pageIndicatorsView != null) {
-                pageIndicatorsView.setAlpha(0.01f);
-                ObjectAnimator indicatorsAlpha =
-                        ObjectAnimator.ofFloat(pageIndicatorsView, "alpha", 1f);
-                indicatorsAlpha.setDuration(revealDuration);
-                mStateAnimation.play(indicatorsAlpha);
-            }
-
             // Setup the animation for the content view
             contentView.setVisibility(View.VISIBLE);
             contentView.setAlpha(0f);
@@ -354,8 +345,9 @@
                         }
                     }
 
-                    // Hide the search bar
-                    mCb.onStateTransitionHideSearchBar();
+                    if (hideSearchBar) {
+                        mCb.onStateTransitionHideSearchBar();
+                    }
 
                     // This can hold unnecessary references to views.
                     mStateAnimation = null;
@@ -414,8 +406,9 @@
             // Show the content view
             contentView.setVisibility(View.VISIBLE);
 
-            // Hide the search bar
-            mCb.onStateTransitionHideSearchBar();
+            if (hideSearchBar) {
+                mCb.onStateTransitionHideSearchBar();
+            }
 
             dispatchOnLauncherTransitionPrepare(fromView, animated, false);
             dispatchOnLauncherTransitionStart(fromView, animated, false);
@@ -484,8 +477,7 @@
             }
         };
         startAnimationToWorkspaceFromOverlay(toWorkspaceState, appsView, appsView.getContentView(),
-                appsView.getRevealView(), null /* pageIndicatorsView */, animated,
-                onCompleteRunnable, cb);
+                appsView.getRevealView(), animated, onCompleteRunnable, cb);
     }
 
     /**
@@ -516,8 +508,8 @@
             }
         };
         startAnimationToWorkspaceFromOverlay(toWorkspaceState, widgetsView,
-                widgetsView.getContentView(), widgetsView.getRevealView(),
-                null, animated, onCompleteRunnable, cb);
+                widgetsView.getContentView(), widgetsView.getRevealView(), animated,
+                onCompleteRunnable, cb);
     }
 
     /**
@@ -525,8 +517,8 @@
      */
     private void startAnimationToWorkspaceFromOverlay(final Workspace.State toWorkspaceState,
               final View fromView, final View contentView, final View revealView,
-              final View pageIndicatorsView, final boolean animated,
-              final Runnable onCompleteRunnable, final PrivateTransitionCallbacks pCb) {
+              final boolean animated, final Runnable onCompleteRunnable,
+              final PrivateTransitionCallbacks pCb) {
         final Resources res = mLauncher.getResources();
         final boolean material = Utilities.isLmpOrAbove();
         final int revealDuration = res.getInteger(R.integer.config_appsCustomizeRevealTime);
@@ -631,16 +623,6 @@
                 itemsAlpha.setInterpolator(decelerateInterpolator);
                 mStateAnimation.play(itemsAlpha);
 
-                // Setup the page indicators animation
-                if (pageIndicatorsView != null) {
-                    pageIndicatorsView.setAlpha(1f);
-                    ObjectAnimator indicatorsAlpha =
-                            LauncherAnimUtils.ofFloat(pageIndicatorsView, "alpha", 0f);
-                    indicatorsAlpha.setDuration(revealDuration);
-                    indicatorsAlpha.setInterpolator(new DecelerateInterpolator(1.5f));
-                    mStateAnimation.play(indicatorsAlpha);
-                }
-
                 if (material) {
                     // Animate the all apps button
                     float finalRadius = pCb.getMaterialRevealViewStartFinalRadius();
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 8cc99a0..9173971 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1700,7 +1700,11 @@
 
         mLastCustomContentScrollProgress = progress;
 
-        mLauncher.getDragLayer().setBackgroundAlpha(progress * 0.8f);
+        // We should only update the drag layer background alpha if we are not in all apps or the
+        // widgets tray
+        if (mState == State.NORMAL) {
+            mLauncher.getDragLayer().setBackgroundAlpha(progress * 0.8f);
+        }
 
         if (mLauncher.getHotseat() != null) {
             mLauncher.getHotseat().setTranslationX(translationX);
@@ -2252,7 +2256,8 @@
         float finalBackgroundAlpha = (stateIsSpringLoaded || stateIsOverview) ? 1.0f : 0f;
         float finalHotseatAndPageIndicatorAlpha = (stateIsNormal || stateIsSpringLoaded) ? 1f : 0f;
         float finalOverviewPanelAlpha = stateIsOverview ? 1f : 0f;
-        float finalSearchBarAlpha = !stateIsNormal ? 0f : 1f;
+        // We keep the search bar visible on the workspace and in AllApps now
+        float finalSearchBarAlpha = (stateIsNormal || stateIsNormalHidden) ? 1f : 0f;
         float finalWorkspaceTranslationY = stateIsOverview || stateIsOverviewHidden ?
                 getOverviewModeTranslationY() : 0;