Removing old scroll indicator and adding page indicator dots.

Change-Id: I44c5b4b532e8464010d45dd0a3dfeccb2d475216
diff --git a/res/drawable-hdpi/active_page.png b/res/drawable-hdpi/active_page.png
new file mode 100644
index 0000000..ce2d5b1
--- /dev/null
+++ b/res/drawable-hdpi/active_page.png
Binary files differ
diff --git a/res/drawable-hdpi/inactive_page.png b/res/drawable-hdpi/inactive_page.png
new file mode 100644
index 0000000..2186f51
--- /dev/null
+++ b/res/drawable-hdpi/inactive_page.png
Binary files differ
diff --git a/res/drawable-mdpi/active_page.png b/res/drawable-mdpi/active_page.png
new file mode 100644
index 0000000..9e23ecc
--- /dev/null
+++ b/res/drawable-mdpi/active_page.png
Binary files differ
diff --git a/res/drawable-mdpi/inactive_page.png b/res/drawable-mdpi/inactive_page.png
new file mode 100644
index 0000000..9468a62
--- /dev/null
+++ b/res/drawable-mdpi/inactive_page.png
Binary files differ
diff --git a/res/drawable-xhdpi/active_page.png b/res/drawable-xhdpi/active_page.png
new file mode 100644
index 0000000..c43e67c
--- /dev/null
+++ b/res/drawable-xhdpi/active_page.png
Binary files differ
diff --git a/res/drawable-xhdpi/inactive_page.png b/res/drawable-xhdpi/inactive_page.png
new file mode 100644
index 0000000..ae3f988
--- /dev/null
+++ b/res/drawable-xhdpi/inactive_page.png
Binary files differ
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 6dfbf21..8ee1413 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -45,9 +45,7 @@
             launcher:cellCountY="@integer/cell_count_y"
             launcher:pageSpacing="@dimen/workspace_page_spacing"
             launcher:scrollIndicatorPaddingLeft="@dimen/qsb_bar_height"
-            launcher:scrollIndicatorPaddingRight="@dimen/button_bar_height">
-
-        </com.android.launcher3.Workspace>
+            launcher:scrollIndicatorPaddingRight="@dimen/button_bar_height" />
 
         <include
             android:id="@+id/qsb_divider"
@@ -57,21 +55,6 @@
             android:layout_marginStart="@dimen/qsb_bar_height"
             android:layout_gravity="start" />
 
-        <include
-            android:id="@+id/dock_divider"
-            layout="@layout/workspace_divider"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_marginEnd="@dimen/button_bar_height"
-            android:layout_gravity="end" />
-
-        <include
-            android:id="@+id/paged_view_indicator"
-            layout="@layout/scroll_indicator"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="bottom" />
-
         <include layout="@layout/hotseat"
             android:id="@+id/hotseat"
             android:layout_width="@dimen/button_bar_height_plus_padding"
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 30eba1c..0fee045 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -33,20 +33,12 @@
         <!-- Keep these behind the workspace so that they are not visible when
              we go into AllApps -->
         <include
-            android:id="@+id/dock_divider"
-            layout="@layout/workspace_divider"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="@dimen/button_bar_height"
-            android:layout_gravity="bottom" />
-
-        <include
-            android:id="@+id/paged_view_indicator"
-            layout="@layout/scroll_indicator"
+            android:id="@+id/page_indicator"
+            layout="@layout/page_indicator"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_gravity="bottom"
-            android:layout_marginBottom="@dimen/button_bar_height" />
+            android:layout_gravity="bottom|center_horizontal"
+            android:layout_marginBottom="@dimen/button_bar_height_plus_padding" />
 
         <!-- The workspace contains 5 screens of cells -->
         <com.android.launcher3.Workspace
@@ -62,6 +54,7 @@
             launcher:cellCountX="@integer/cell_count_x"
             launcher:cellCountY="@integer/cell_count_y"
             launcher:pageSpacing="@dimen/workspace_page_spacing"
+            launcher:pageIndicator="@id/page_indicator"
             launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left"
             launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right">
         </com.android.launcher3.Workspace>
diff --git a/res/layout-sw600dp-land/launcher.xml b/res/layout-sw600dp-land/launcher.xml
new file mode 100644
index 0000000..8e45028
--- /dev/null
+++ b/res/layout-sw600dp-land/launcher.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Full screen view projects under the status bar and contains the background -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+
+    android:id="@+id/launcher"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/workspace_bg">
+
+    <com.android.launcher3.DragLayer
+        android:id="@+id/drag_layer"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:fitsSystemWindows="true">
+
+        <include
+            android:id="@+id/page_indicator"
+            layout="@layout/page_indicator"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="bottom|center_horizontal" />
+
+        <!-- The workspace contains 5 screens of cells -->
+        <com.android.launcher3.Workspace
+            android:id="@+id/workspace"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="center"
+            android:paddingStart="@dimen/workspace_left_padding"
+            android:paddingEnd="@dimen/workspace_right_padding"
+            android:paddingTop="@dimen/workspace_top_padding"
+            android:paddingBottom="@dimen/workspace_bottom_padding"
+            launcher:defaultScreen="@integer/config_workspaceDefaultScreen"
+            launcher:cellCountX="@integer/cell_count_x"
+            launcher:cellCountY="@integer/cell_count_y"
+            launcher:pageSpacing="@dimen/workspace_page_spacing"
+            launcher:pageIndicator="@id/page_indicator"
+            launcher:scrollIndicatorPaddingLeft="@dimen/qsb_bar_height"
+            launcher:scrollIndicatorPaddingRight="@dimen/button_bar_height" />
+
+        <include
+            android:id="@+id/qsb_divider"
+            layout="@layout/workspace_divider"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginStart="@dimen/qsb_bar_height"
+            android:layout_gravity="start" />
+
+        <include layout="@layout/hotseat"
+            android:id="@+id/hotseat"
+            android:layout_width="@dimen/button_bar_height_plus_padding"
+            android:layout_height="match_parent"
+            android:layout_gravity="end" />
+
+        <include
+            android:id="@+id/qsb_bar"
+            layout="@layout/qsb_bar" />
+
+        <!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure
+             that it is still visible during the transition to AllApps and doesn't overlay on
+             top of that view. -->
+        <include layout="@layout/workspace_cling"
+            android:id="@+id/workspace_cling"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:visibility="gone" />
+
+        <include layout="@layout/folder_cling"
+            android:id="@+id/folder_cling"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:visibility="gone" />
+
+        <com.android.launcher3.DrawableStateProxyView
+            android:id="@+id/voice_button_proxy"
+            android:layout_width="@dimen/qsb_bar_height"
+            android:layout_height="@dimen/app_icon_size"
+            android:layout_gravity="top|start"
+            android:layout_marginTop="64dp"
+            android:clickable="true"
+            android:onClick="onClickVoiceButton"
+            android:importantForAccessibility="no"
+            launcher:sourceViewId="@+id/voice_button" />
+
+        <include layout="@layout/apps_customize_pane"
+            android:id="@+id/apps_customize_pane"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:visibility="invisible" />
+    </com.android.launcher3.DragLayer>
+</FrameLayout>
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index dff3b26..852d1ec 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -33,19 +33,11 @@
         <!-- Keep these behind the workspace so that they are not visible when
              we go into AllApps -->
         <include
-            android:id="@+id/dock_divider"
-            layout="@layout/workspace_divider"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="@dimen/button_bar_height_plus_padding"
-            android:layout_gravity="bottom|center_horizontal" />
-
-        <include
-            android:id="@+id/paged_view_indicator"
-            layout="@layout/scroll_indicator"
+            android:id="@+id/page_indicator"
+            layout="@layout/page_indicator"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_gravity="bottom"
+            android:layout_gravity="bottom|center_horizontal"
             android:layout_marginBottom="@dimen/button_bar_height_plus_padding" />
 
         <!-- The workspace contains 5 screens of cells -->
@@ -62,6 +54,7 @@
             launcher:cellCountX="@integer/cell_count_x"
             launcher:cellCountY="@integer/cell_count_y"
             launcher:pageSpacing="@dimen/workspace_page_spacing"
+            launcher:pageIndicator="@id/page_indicator"
             launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left"
             launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right">
         </com.android.launcher3.Workspace>
diff --git a/res/layout/apps_customize_pane.xml b/res/layout/apps_customize_pane.xml
index 7efe486..c64b7ce 100644
--- a/res/layout/apps_customize_pane.xml
+++ b/res/layout/apps_customize_pane.xml
@@ -55,6 +55,7 @@
                 android:id="@+id/apps_customize_pane_content"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
+                android:layout_marginBottom="@dimen/apps_customize_page_indicator_height"
                 android:layout_gravity="center"
                 launcher:maxAppCellCountX="@integer/apps_customize_maxCellCountX"
                 launcher:maxAppCellCountY="@integer/apps_customize_maxCellCountY"
@@ -70,20 +71,21 @@
                 launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y"
                 launcher:clingFocusedX="@integer/apps_customize_cling_focused_x"
                 launcher:clingFocusedY="@integer/apps_customize_cling_focused_y"
-                launcher:maxGap="@dimen/workspace_max_gap" />
+                launcher:maxGap="@dimen/workspace_max_gap"
+                launcher:pageIndicator="@+id/page_indicator" />
             <FrameLayout
                 android:id="@+id/animation_buffer"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:background="#FF000000"
                 android:visibility="gone" />
-
             <include
-                android:id="@+id/paged_view_indicator"
-                layout="@layout/scroll_indicator"
+                android:id="@+id/page_indicator"
+                layout="@layout/page_indicator"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_gravity="bottom" />
+                android:layout_gravity="bottom|center_horizontal"
+                android:layout_marginBottom="@dimen/apps_customize_page_indicator_margin" />
         </FrameLayout>
     </LinearLayout>
 
diff --git a/res/layout/page_indicator.xml b/res/layout/page_indicator.xml
new file mode 100644
index 0000000..8aae752
--- /dev/null
+++ b/res/layout/page_indicator.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.PageIndicator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+    android:animateLayoutChanges="true">
+</com.android.launcher3.PageIndicator>
diff --git a/res/layout/page_indicator_marker.xml b/res/layout/page_indicator_marker.xml
new file mode 100644
index 0000000..0260e7e
--- /dev/null
+++ b/res/layout/page_indicator_marker.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.PageIndicatorMarker
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+    <ImageView
+        android:id="@+id/inactive"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/inactive_page"
+        />
+    <ImageView
+        android:id="@+id/active"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/active_page"
+        android:alpha="0"
+        />
+</com.android.launcher3.PageIndicatorMarker>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 0c37e3c..1545083 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -97,6 +97,8 @@
         <attr name="pageLayoutPaddingRight" format="dimension" />
         <!-- The space between adjacent pages of the PagedView. -->
         <attr name="pageSpacing" format="dimension" />
+        <!-- The page indicator for this workspace -->
+        <attr name="pageIndicator" format="reference" />
         <!-- The padding for the scroll indicator area -->
         <attr name="scrollIndicatorPaddingLeft" format="dimension" />
         <attr name="scrollIndicatorPaddingRight" format="dimension" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 3fe53d2..2bfb31c 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -77,6 +77,10 @@
     <dimen name="apps_customize_widget_cell_width_gap">10dp</dimen>
     <dimen name="apps_customize_widget_cell_height_gap">8dp</dimen>
 
+    <!-- The AppsCustomize page indicator -->
+    <dimen name="apps_customize_page_indicator_height">12dp</dimen>
+    <dimen name="apps_customize_page_indicator_margin">4dp</dimen>
+
     <!-- height of the bottom row of controls -->
     <dimen name="button_bar_height">62dip</dimen>
     <!-- Because portal animations go beyond the bounds of an icon, we need
diff --git a/src/com/android/launcher3/AppsCustomizeTabHost.java b/src/com/android/launcher3/AppsCustomizeTabHost.java
index 51d2fba..9868e8b 100644
--- a/src/com/android/launcher3/AppsCustomizeTabHost.java
+++ b/src/com/android/launcher3/AppsCustomizeTabHost.java
@@ -178,13 +178,9 @@
     }
 
     private void onTabChangedStart() {
-        mAppsCustomizePane.hideScrollingIndicator(false);
     }
 
     private void reloadCurrentPage() {
-        if (!LauncherAppState.getInstance().isScreenLarge()) {
-            mAppsCustomizePane.flashScrollingIndicator(true);
-        }
         mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage());
         mAppsCustomizePane.requestFocus();
     }
@@ -370,9 +366,6 @@
         if (toWorkspace) {
             // Going from All Apps -> Workspace
             setVisibilityOfSiblingsWithLowerZOrder(VISIBLE);
-            // Stop the scrolling indicator - we don't want All Apps to be invalidating itself
-            // during the transition, especially since it has a hardware layer set on it
-            mAppsCustomizePane.cancelScrollingIndicatorAnimations();
         } else {
             // Going from Workspace -> All Apps
             mContent.setVisibility(VISIBLE);
@@ -380,10 +373,6 @@
             // Make sure the current page is loaded (we start loading the side pages after the
             // transition to prevent slowing down the animation)
             mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage(), true);
-
-            if (!LauncherAppState.getInstance().isScreenLarge()) {
-                mAppsCustomizePane.showScrollingIndicator(true);
-            }
         }
 
         if (mResetAfterTransition) {
@@ -421,10 +410,6 @@
             // prevent slowing down the animation)
             mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage());
 
-            if (!LauncherAppState.getInstance().isScreenLarge()) {
-                mAppsCustomizePane.hideScrollingIndicator(false);
-            }
-
             // Going from Workspace -> All Apps
             // NOTE: We should do this at the end since we check visibility state in some of the
             // cling initialization/dismiss code above.
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index d1284d8..d46deb2 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -203,7 +203,6 @@
 
     private Workspace mWorkspace;
     private View mQsbDivider;
-    private View mDockDivider;
     private View mLauncherView;
     private DragLayer mDragLayer;
     private DragController mDragController;
@@ -982,7 +981,6 @@
         mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
         mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
         mQsbDivider = findViewById(R.id.qsb_divider);
-        mDockDivider = findViewById(R.id.dock_divider);
 
         mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
         mWorkspaceBackgroundDrawable = getResources().getDrawable(R.drawable.workspace_bg);
@@ -2666,8 +2664,6 @@
                     if (mWorkspace != null
                             && !springLoaded
                             && !LauncherAppState.getInstance().isScreenLarge()) {
-                        // Hide the workspace scrollbar
-                        mWorkspace.hideScrollingIndicator(true);
                         hideDockDivider();
                     }
                     if (!animationCancelled) {
@@ -2736,8 +2732,6 @@
             toView.bringToFront();
 
             if (!springLoaded && !LauncherAppState.getInstance().isScreenLarge()) {
-                // Hide the workspace scrollbar
-                mWorkspace.hideScrollingIndicator(true);
                 hideDockDivider();
 
                 // Hide the search bar
@@ -2825,9 +2819,6 @@
                     fromView.setVisibility(View.GONE);
                     dispatchOnLauncherTransitionEnd(fromView, animated, true);
                     dispatchOnLauncherTransitionEnd(toView, animated, true);
-                    if (mWorkspace != null) {
-                        mWorkspace.hideScrollingIndicator(false);
-                    }
                     if (onCompleteRunnable != null) {
                         onCompleteRunnable.run();
                     }
@@ -2851,7 +2842,6 @@
             dispatchOnLauncherTransitionPrepare(toView, animated, true);
             dispatchOnLauncherTransitionStart(toView, animated, true);
             dispatchOnLauncherTransitionEnd(toView, animated, true);
-            mWorkspace.hideScrollingIndicator(false);
         }
     }
 
@@ -2905,8 +2895,6 @@
             }
         }
 
-        mWorkspace.flashScrollingIndicator(animated);
-
         // Change the state *after* we've called all the transition code
         mState = State.WORKSPACE;
 
@@ -2984,26 +2972,22 @@
     }
 
     void hideDockDivider() {
-        if (mQsbDivider != null && mDockDivider != null) {
+        if (mQsbDivider != null) {
             mQsbDivider.setVisibility(View.INVISIBLE);
-            mDockDivider.setVisibility(View.INVISIBLE);
         }
     }
 
     void showDockDivider(boolean animated) {
-        if (mQsbDivider != null && mDockDivider != null) {
+        if (mQsbDivider != null) {
             mQsbDivider.setVisibility(View.VISIBLE);
-            mDockDivider.setVisibility(View.VISIBLE);
             if (mDividerAnimator != null) {
                 mDividerAnimator.cancel();
                 mQsbDivider.setAlpha(1f);
-                mDockDivider.setAlpha(1f);
                 mDividerAnimator = null;
             }
             if (animated) {
                 mDividerAnimator = LauncherAnimUtils.createAnimatorSet();
-                mDividerAnimator.playTogether(LauncherAnimUtils.ofFloat(mQsbDivider, "alpha", 1f),
-                        LauncherAnimUtils.ofFloat(mDockDivider, "alpha", 1f));
+                mDividerAnimator.playTogether(LauncherAnimUtils.ofFloat(mQsbDivider, "alpha", 1f));
                 int duration = 0;
                 if (mSearchDropTargetBar != null) {
                     duration = mSearchDropTargetBar.getTransitionInDuration();
diff --git a/src/com/android/launcher3/PageIndicator.java b/src/com/android/launcher3/PageIndicator.java
new file mode 100644
index 0000000..ecaa8f5
--- /dev/null
+++ b/src/com/android/launcher3/PageIndicator.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 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.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.LayoutTransition;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import com.android.launcher3.R;
+
+import java.util.ArrayList;
+
+public class PageIndicator extends LinearLayout {
+    @SuppressWarnings("unused")
+    private static final String TAG = "PageIndicator";
+
+    private LayoutInflater mLayoutInflater;
+
+    public PageIndicator(Context context) {
+        this(context, null);
+    }
+
+    public PageIndicator(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public PageIndicator(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mLayoutInflater = LayoutInflater.from(context);
+
+        LayoutTransition transition = getLayoutTransition();
+        transition.setDuration(250);
+    }
+
+    void addMarker(int index) {
+        index = Math.max(0, Math.min(index, getChildCount()));
+        View marker = mLayoutInflater.inflate(R.layout.page_indicator_marker, this, false);
+        addView(marker, index);
+    }
+    void addMarkers(int count) {
+        for (int i = 0; i < count; ++i) {
+            addMarker(Integer.MAX_VALUE);
+        }
+    }
+
+    void removeMarker(int index) {
+        if (getChildCount() > 0) {
+            index = Math.max(0, Math.min(index, getChildCount() - 1));
+            removeViewAt(index);
+        }
+    }
+    void removeAllMarkers() {
+        while (getChildCount() > 0) {
+            removeMarker(Integer.MAX_VALUE);
+        }
+    }
+
+    void setActiveMarker(int index) {
+        for (int i = 0; i < getChildCount(); ++i) {
+            PageIndicatorMarker marker = (PageIndicatorMarker) getChildAt(i);
+            if (index == i) {
+                marker.activate();
+            } else {
+                marker.inactivate();
+            }
+        }
+    }
+}
diff --git a/src/com/android/launcher3/PageIndicatorMarker.java b/src/com/android/launcher3/PageIndicatorMarker.java
new file mode 100644
index 0000000..852ee51
--- /dev/null
+++ b/src/com/android/launcher3/PageIndicatorMarker.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011 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.animation.LayoutTransition;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import com.android.launcher3.R;
+
+public class PageIndicatorMarker extends FrameLayout {
+    @SuppressWarnings("unused")
+    private static final String TAG = "PageIndicator";
+
+    private static final int MARKER_FADE_DURATION = 150;
+
+    private View mActiveMarker;
+    private View mInactiveMarker;
+
+    public PageIndicatorMarker(Context context) {
+        this(context, null);
+    }
+
+    public PageIndicatorMarker(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public PageIndicatorMarker(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    protected void onFinishInflate() {
+        mActiveMarker = findViewById(R.id.active);
+        mInactiveMarker = findViewById(R.id.inactive);
+    }
+
+    public void activate() {
+        mActiveMarker.animate().alpha(1f)
+                .setDuration(MARKER_FADE_DURATION).start();
+        mInactiveMarker.animate().alpha(0f)
+                .setDuration(MARKER_FADE_DURATION).start();
+    }
+    public void inactivate() {
+        mInactiveMarker.animate().alpha(1f)
+                .setDuration(MARKER_FADE_DURATION).start();
+        mActiveMarker.animate().alpha(0f)
+                .setDuration(MARKER_FADE_DURATION).start();
+    }
+}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 275195b..81a842e 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -192,18 +192,9 @@
 
     protected boolean mAllowLongPress = true;
 
-    // Scrolling indicator
-    private ValueAnimator mScrollIndicatorAnimator;
-    private View mScrollIndicator;
-    private int mScrollIndicatorPaddingLeft;
-    private int mScrollIndicatorPaddingRight;
-    private boolean mHasScrollIndicator = true;
-    private boolean mShouldShowScrollIndicator = false;
-    private boolean mShouldShowScrollIndicatorImmediately = false;
-    protected static final int sScrollIndicatorFadeInDuration = 150;
-    protected static final int sScrollIndicatorFadeOutDuration = 650;
-    protected static final int sScrollIndicatorFlashDuration = 650;
-    private boolean mScrollingPaused = false;
+    // Page Indicator
+    private int mPageIndicatorViewId;
+    private PageIndicator mPageIndicator;
 
     // The viewport whether the pages are to be contained (the actual view may be larger than the
     // viewport)
@@ -296,10 +287,7 @@
                 R.styleable.PagedView_pageLayoutWidthGap, 0);
         mPageLayoutHeightGap = a.getDimensionPixelSize(
                 R.styleable.PagedView_pageLayoutHeightGap, 0);
-        mScrollIndicatorPaddingLeft =
-            a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingLeft, 0);
-        mScrollIndicatorPaddingRight =
-            a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingRight, 0);
+        mPageIndicatorViewId = a.getResourceId(R.styleable.PagedView_pageIndicator, -1);
         a.recycle();
 
         setHapticFeedbackEnabled(false);
@@ -332,6 +320,21 @@
         setOnHierarchyChangeListener(this);
     }
 
+    protected void onAttachedToWindow() {
+        // Hook up the page indicator
+        ViewGroup parent = (ViewGroup) getParent();
+        if (mPageIndicator == null && mPageIndicatorViewId > -1) {
+            mPageIndicator = (PageIndicator) parent.findViewById(mPageIndicatorViewId);
+            mPageIndicator.removeAllMarkers();
+            mPageIndicator.addMarkers(getChildCount());
+        }
+    }
+
+    protected void onDetachedFromWindow() {
+        // Unhook the page indicator
+        mPageIndicator = null;
+    }
+
     void setDeleteDropTarget(View v) {
         mDeleteDropTarget = v;
     }
@@ -473,8 +476,6 @@
      */
     void pauseScrolling() {
         mScroller.forceFinished(true);
-        cancelScrollingIndicatorAnimations();
-        mScrollingPaused = true;
     }
 
     /**
@@ -482,7 +483,6 @@
      * @see #pauseScrolling()
      */
     void resumeScrolling() {
-        mScrollingPaused = false;
     }
     /**
      * Sets the current page.
@@ -499,8 +499,6 @@
 
         mForceScreenScrolled = true;
         mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1));
-        updateCurrentPageScroll();
-        updateScrollingIndicator();
         notifyPageSwitchListener();
         invalidate();
     }
@@ -509,6 +507,11 @@
         if (mPageSwitchListener != null) {
             mPageSwitchListener.onPageSwitch(getPageAt(mCurrentPage), mCurrentPage);
         }
+
+        // Update the page indicator (when we aren't reordering)
+        if (mPageIndicator != null && !isReordering(false)) {
+            mPageIndicator.setActiveMarker(getNextPage());
+        }
     }
     protected void pageBeginMoving() {
         if (!mIsPageMoving) {
@@ -750,8 +753,6 @@
             }
         }
 
-        updateScrollingIndicatorPosition();
-
         if (childCount > 0) {
             final int index = isLayoutRtl() ? 0 : childCount - 1;
             mMaxScrollX = getChildOffset(index) - getRelativeChildOffset(index);
@@ -814,9 +815,6 @@
     }
 
     protected void screenScrolled(int screenCenter) {
-        if (isScrollingIndicatorEnabled()) {
-            updateScrollingIndicator();
-        }
         boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
 
         if (mFadeInAdjacentScreens && !isInOverscroll) {
@@ -834,6 +832,12 @@
 
     @Override
     public void onChildViewAdded(View parent, View child) {
+        // Update the page indicator, we don't update the page indicator as we
+        // add/remove pages
+        if (mPageIndicator != null && !isReordering(false)) {
+            mPageIndicator.addMarker(indexOfChild(child));
+        }
+
         // This ensures that when children are added, they get the correct transforms / alphas
         // in accordance with any scroll effects.
         mForceScreenScrolled = true;
@@ -849,6 +853,46 @@
         invalidateCachedOffsets();
     }
 
+    private void removeMarkerForView(int index) {
+        // Update the page indicator, we don't update the page indicator as we
+        // add/remove pages
+        if (mPageIndicator != null && !isReordering(false)) {
+            mPageIndicator.removeMarker(index);
+        }
+    }
+
+    @Override
+    public void removeView(View v) {
+        // XXX: We should find a better way to hook into this before the view
+        // gets removed form its parent...
+        removeMarkerForView(indexOfChild(v));
+        super.removeView(v);
+    }
+    @Override
+    public void removeViewInLayout(View v) {
+        // XXX: We should find a better way to hook into this before the view
+        // gets removed form its parent...
+        removeMarkerForView(indexOfChild(v));
+        super.removeViewInLayout(v);
+    }
+    @Override
+    public void removeViewAt(int index) {
+        // XXX: We should find a better way to hook into this before the view
+        // gets removed form its parent...
+        removeViewAt(index);
+        super.removeViewAt(index);
+    }
+    @Override
+    public void removeAllViewsInLayout() {
+        // Update the page indicator, we don't update the page indicator as we
+        // add/remove pages
+        if (mPageIndicator != null) {
+            mPageIndicator.removeAllMarkers();
+        }
+
+        super.removeAllViewsInLayout();
+    }
+
     protected void invalidateCachedOffsets() {
         int count = getChildCount();
         if (count == 0) {
@@ -1605,6 +1649,7 @@
                                 addView(mDragView, pageUnderPointIndex);
                                 onAddView(mDragView, pageUnderPointIndex);
                                 mSidePageHoverIndex = -1;
+                                mPageIndicator.setActiveMarker(getNextPage());
                             }
                         };
                         postDelayed(mSidePageHoverRunnable, REORDERING_SIDE_PAGE_HOVER_TIMEOUT);
@@ -2172,153 +2217,6 @@
         }
     }
 
-    protected View getScrollingIndicator() {
-        // We use mHasScrollIndicator to prevent future lookups if there is no sibling indicator
-        // found
-        if (mHasScrollIndicator && mScrollIndicator == null) {
-            ViewGroup parent = (ViewGroup) getParent();
-            if (parent != null) {
-                mScrollIndicator = (View) (parent.findViewById(R.id.paged_view_indicator));
-                mHasScrollIndicator = mScrollIndicator != null;
-                if (mHasScrollIndicator) {
-                    mScrollIndicator.setVisibility(View.VISIBLE);
-                }
-            }
-        }
-        return mScrollIndicator;
-    }
-
-    protected boolean isScrollingIndicatorEnabled() {
-        return true;
-    }
-
-    Runnable hideScrollingIndicatorRunnable = new Runnable() {
-        @Override
-        public void run() {
-            hideScrollingIndicator(false);
-        }
-    };
-
-    protected void flashScrollingIndicator(boolean animated) {
-        removeCallbacks(hideScrollingIndicatorRunnable);
-        showScrollingIndicator(!animated);
-        postDelayed(hideScrollingIndicatorRunnable, sScrollIndicatorFlashDuration);
-    }
-
-    protected void showScrollingIndicator(boolean immediately) {
-        mShouldShowScrollIndicator = true;
-        mShouldShowScrollIndicatorImmediately = true;
-        if (getChildCount() <= 1) return;
-        if (!isScrollingIndicatorEnabled()) return;
-
-        mShouldShowScrollIndicator = false;
-        getScrollingIndicator();
-        if (mScrollIndicator != null) {
-            // Fade the indicator in
-            updateScrollingIndicatorPosition();
-            mScrollIndicator.setVisibility(View.VISIBLE);
-            cancelScrollingIndicatorAnimations();
-            if (immediately) {
-                mScrollIndicator.setAlpha(1f);
-            } else {
-                mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 1f);
-                mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeInDuration);
-                mScrollIndicatorAnimator.start();
-            }
-        }
-    }
-
-    protected void cancelScrollingIndicatorAnimations() {
-        if (mScrollIndicatorAnimator != null) {
-            mScrollIndicatorAnimator.cancel();
-        }
-    }
-
-    protected void hideScrollingIndicator(boolean immediately) {
-        if (getChildCount() <= 1) return;
-        if (!isScrollingIndicatorEnabled()) return;
-
-        getScrollingIndicator();
-        if (mScrollIndicator != null) {
-            // Fade the indicator out
-            updateScrollingIndicatorPosition();
-            cancelScrollingIndicatorAnimations();
-            if (immediately) {
-                mScrollIndicator.setVisibility(View.INVISIBLE);
-                mScrollIndicator.setAlpha(0f);
-            } else {
-                mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 0f);
-                mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeOutDuration);
-                mScrollIndicatorAnimator.addListener(new AnimatorListenerAdapter() {
-                    private boolean cancelled = false;
-                    @Override
-                    public void onAnimationCancel(android.animation.Animator animation) {
-                        cancelled = true;
-                    }
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        if (!cancelled) {
-                            mScrollIndicator.setVisibility(View.INVISIBLE);
-                        }
-                    }
-                });
-                mScrollIndicatorAnimator.start();
-            }
-        }
-    }
-
-    /**
-     * To be overridden by subclasses to determine whether the scroll indicator should stretch to
-     * fill its space on the track or not.
-     */
-    protected boolean hasElasticScrollIndicator() {
-        return true;
-    }
-
-    private void updateScrollingIndicator() {
-        if (getChildCount() <= 1) return;
-        if (!isScrollingIndicatorEnabled()) return;
-
-        getScrollingIndicator();
-        if (mScrollIndicator != null) {
-            updateScrollingIndicatorPosition();
-        }
-        if (mShouldShowScrollIndicator) {
-            showScrollingIndicator(mShouldShowScrollIndicatorImmediately);
-        }
-    }
-
-    private void updateScrollingIndicatorPosition() {
-        final boolean isRtl = isLayoutRtl();
-        if (!isScrollingIndicatorEnabled()) return;
-        if (mScrollIndicator == null) return;
-        int numPages = getChildCount();
-        int pageWidth = getViewportWidth();
-        int lastChildIndex = Math.max(0, getChildCount() - 1);
-        int maxScrollX = getChildOffset(lastChildIndex) - getRelativeChildOffset(lastChildIndex);
-        int trackWidth = pageWidth - mScrollIndicatorPaddingLeft - mScrollIndicatorPaddingRight;
-        int indicatorWidth = mScrollIndicator.getMeasuredWidth() -
-                mScrollIndicator.getPaddingLeft() - mScrollIndicator.getPaddingRight();
-
-        float scrollPos = isRtl ? mMaxScrollX - getScrollX() : getScrollX();
-        float offset = Math.max(0f, Math.min(1f, (float) scrollPos / mMaxScrollX));
-        if (isRtl) {
-            offset = 1f - offset;
-        }
-        int indicatorSpace = trackWidth / numPages;
-        int indicatorPos = (int) (offset * (trackWidth - indicatorSpace)) + mScrollIndicatorPaddingLeft;
-        if (hasElasticScrollIndicator()) {
-            if (mScrollIndicator.getMeasuredWidth() != indicatorSpace) {
-                mScrollIndicator.getLayoutParams().width = indicatorSpace;
-                mScrollIndicator.requestLayout();
-            }
-        } else {
-            int indicatorCenterOffset = indicatorSpace / 2 - indicatorWidth / 2;
-            indicatorPos += indicatorCenterOffset;
-        }
-        mScrollIndicator.setTranslationX(indicatorPos);
-    }
-
     // Animate the drag view back to the original position
     void animateDragViewToOriginalPosition() {
         if (mDragView != null) {
diff --git a/src/com/android/launcher3/PagedViewWithDraggableItems.java b/src/com/android/launcher3/PagedViewWithDraggableItems.java
index 8f10ecf..2a29c33 100644
--- a/src/com/android/launcher3/PagedViewWithDraggableItems.java
+++ b/src/com/android/launcher3/PagedViewWithDraggableItems.java
@@ -167,12 +167,4 @@
         cancelDragging();
         super.onDetachedFromWindow();
     }
-
-    /** Show the scrolling indicators when we move the page */
-    protected void onPageBeginMoving() {
-        showScrollingIndicator(false);
-    }
-    protected void onPageEndMoving() {
-        hideScrollingIndicator(false);
-    }
 }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index d9582ad..47d8ec8 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -329,6 +329,7 @@
         cellCountX = a.getInt(R.styleable.Workspace_cellCountX, cellCountX);
         cellCountY = a.getInt(R.styleable.Workspace_cellCountY, cellCountY);
         mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
+
         a.recycle();
 
         setOnHierarchyChangeListener(this);
@@ -870,9 +871,6 @@
                 ((CellLayout) getPageAt(i)).setShortcutAndWidgetAlpha(1f);
             }
         }
-
-        // Show the scroll indicator as you pan the page
-        showScrollingIndicator(false);
     }
 
     protected void onPageEndMoving() {
@@ -896,11 +894,6 @@
             if (LauncherAppState.getInstance().isScreenLarge()) {
                 hideOutlines();
             }
-
-            // Hide the scroll indicator as you pan the page
-            if (!mDragController.isDragging()) {
-                hideScrollingIndicator(false);
-            }
         }
 
         if (mDelayedResizeRunnable != null) {
@@ -1853,7 +1846,6 @@
     public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
         mIsSwitchingState = true;
         updateChildrenLayersEnabled(false);
-        cancelScrollingIndicatorAnimations();
     }
 
     @Override
@@ -2070,9 +2062,6 @@
         mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
                 DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale);
         b.recycle();
-
-        // Show the scrolling indicator when you pick up an item
-        showScrollingIndicator(false);
     }
 
     void addApplicationShortcut(ShortcutInfo info, CellLayout target, long container, long screenId,
@@ -2353,11 +2342,13 @@
                 // cell also contains a shortcut, then create a folder with the two shortcuts.
                 if (!mInScrollArea && createUserFolderIfNecessary(cell, container,
                         dropTargetLayout, mTargetCell, distance, false, d.dragView, null)) {
+                    stripEmptyScreens();
                     return;
                 }
 
                 if (addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,
                         distance, d, false)) {
+                    stripEmptyScreens();
                     return;
                 }
 
@@ -3463,9 +3454,6 @@
         }
         mDragOutline = null;
         mDragInfo = null;
-
-        // Hide the scrolling indicator after you pick up an item
-        hideScrollingIndicator(false);
     }
 
     void updateItemLocationsInDatabase(CellLayout cl) {
@@ -4025,18 +4013,11 @@
     }
 
     void setFadeForOverScroll(float fade) {
-        if (!isScrollingIndicatorEnabled()) return;
-
         mOverscrollFade = fade;
         float reducedFade = 0.5f + 0.5f * (1 - fade);
         final ViewGroup parent = (ViewGroup) getParent();
         final ImageView qsbDivider = (ImageView) (parent.findViewById(R.id.qsb_divider));
-        final ImageView dockDivider = (ImageView) (parent.findViewById(R.id.dock_divider));
-        final View scrollIndicator = getScrollingIndicator();
 
-        cancelScrollingIndicatorAnimations();
         if (qsbDivider != null) qsbDivider.setAlpha(reducedFade);
-        if (dockDivider != null) dockDivider.setAlpha(reducedFade);
-        scrollIndicator.setAlpha(1 - fade);
     }
 }