Revert "Simplifying some page indicator dots attributes so that it can"

This reverts commit a5ead45967f204fd938846d0d2fa3fa244857708.

Reason for revert: b/274169859

Change-Id: Id214694ae4f61cd70796c6f7e932c1fdef82d746
diff --git a/quickstep/res/layout/taskbar_edu.xml b/quickstep/res/layout/taskbar_edu.xml
index f3856ba..d7daea3 100644
--- a/quickstep/res/layout/taskbar_edu.xml
+++ b/quickstep/res/layout/taskbar_edu.xml
@@ -55,7 +55,7 @@
             style="@style/TaskbarEdu.Button.Close"
             android:textColor="?android:attr/textColorPrimary"/>
 
-        <com.android.launcher3.pageindicators.LauncherDotsPageIndicator
+        <com.android.launcher3.pageindicators.PageIndicatorDots
             android:id="@+id/content_page_indicator"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
@@ -63,7 +63,6 @@
             app:layout_constraintBottom_toBottomOf="@id/edu_start_button"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
-            app:indicatorDotColor="@color/folder_pagination_color"
             android:elevation="1dp" />
 
         <Button
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
index d0e6386..6cd6512 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
@@ -25,12 +25,12 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.PagedView;
 import com.android.launcher3.R;
-import com.android.launcher3.pageindicators.LauncherDotsPageIndicator;
+import com.android.launcher3.pageindicators.PageIndicatorDots;
 import com.android.launcher3.taskbar.TaskbarEduController.TaskbarEduCallbacks;
 import com.android.launcher3.views.ActivityContext;
 
 /** Horizontal carousel of tutorial screens for Taskbar Edu. */
-public class TaskbarEduPagedView extends PagedView<LauncherDotsPageIndicator> {
+public class TaskbarEduPagedView extends PagedView<PageIndicatorDots> {
 
     private TaskbarEduView mTaskbarEduView;
     private TaskbarEduCallbacks mControllerCallbacks;
diff --git a/res/drawable/page_indicator.xml b/res/drawable/page_indicator.xml
new file mode 100644
index 0000000..c0ccc49
--- /dev/null
+++ b/res/drawable/page_indicator.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="?attr/folderPaginationColor"/>
+    <size android:width="@dimen/page_indicator_size" android:height="@dimen/page_indicator_size"/>
+</shape>
\ No newline at end of file
diff --git a/res/layout/page_indicator_dots.xml b/res/layout/page_indicator_dots.xml
index 41844b7..d5fe51e 100644
--- a/res/layout/page_indicator_dots.xml
+++ b/res/layout/page_indicator_dots.xml
@@ -14,13 +14,9 @@
      limitations under the License.
 -->
 
-<com.android.launcher3.pageindicators.LauncherDotsPageIndicator
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res-auto"
+<com.android.launcher3.pageindicators.PageIndicatorDots xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/page_indicator"
     android:layout_width="match_parent"
     android:layout_height="@dimen/workspace_page_indicator_height"
     android:layout_gravity="bottom | center_horizontal"
-    android:theme="@style/HomeScreenElementTheme"
-    launcher:indicatorDotColor="?attr/workspaceTextColor"
-    />
\ No newline at end of file
+    android:theme="@style/HomeScreenElementTheme" />
\ No newline at end of file
diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml
index 35ccc5a..5518dc8 100644
--- a/res/layout/user_folder_icon_normalized.xml
+++ b/res/layout/user_folder_icon_normalized.xml
@@ -53,13 +53,12 @@
             android:textColorHighlight="?android:attr/colorControlHighlight"
             android:textColorHint="?attr/folderHintColor"/>
 
-        <com.android.launcher3.pageindicators.LauncherDotsPageIndicator
+        <com.android.launcher3.pageindicators.PageIndicatorDots
             android:id="@+id/folder_page_indicator"
             android:layout_gravity="center_vertical"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:elevation="1dp"
-            launcher:indicatorDotColor="@color/folder_pagination_color"
             />
 
     </LinearLayout>
diff --git a/res/values-night-v31/colors.xml b/res/values-night-v31/colors.xml
index 3b85b88..f331361 100644
--- a/res/values-night-v31/colors.xml
+++ b/res/values-night-v31/colors.xml
@@ -26,6 +26,4 @@
     <color name="home_settings_track_off_color">@android:color/system_neutral1_700</color>
 
     <color name="all_apps_button_color">@android:color/system_neutral2_200</color>
-
-    <color name="folder_pagination_color">@android:color/system_accent2_100</color>
 </resources>
\ No newline at end of file
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index ee27d99..17fe419 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -18,6 +18,4 @@
 
 <resources>
     <color name="all_apps_button_color">#BFC8CC</color>
-    <color name="folder_pagination_color">#ffbfebe3</color>
-
 </resources>
\ No newline at end of file
diff --git a/res/values-v31/colors.xml b/res/values-v31/colors.xml
index 0c87ff4..054fe47 100644
--- a/res/values-v31/colors.xml
+++ b/res/values-v31/colors.xml
@@ -41,7 +41,8 @@
     <color name="wallpaper_popup_scrim">@android:color/system_neutral1_900</color>
 
     <color name="folder_dot_color">@android:color/system_accent3_100</color>
-    <color name="folder_pagination_color">@android:color/system_accent1_600</color>
+    <color name="folder_pagination_color_light">@android:color/system_accent1_600</color>
+    <color name="folder_pagination_color_dark">@android:color/system_accent2_100</color>
 
     <color name="home_settings_header_accent">@android:color/system_accent1_600</color>
     <color name="home_settings_header_collapsed">@android:color/system_neutral1_100</color>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 5bacebc..96938ca 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -42,6 +42,7 @@
     <attr name="popupNotificationDotColor" format="color" />
 
     <attr name="folderDotColor" format="color" />
+    <attr name="folderPaginationColor" format="color" />
     <attr name="folderPreviewColor" format="color" />
     <attr name="folderBackgroundColor" format="color" />
     <attr name="folderIconRadius" format="float" />
@@ -481,10 +482,4 @@
         <!-- The icon drawable of a widget category. -->
         <attr name="sectionDrawable" format="reference" />
     </declare-styleable>
-
-    <!-- Attributes for PagedIndicator -->
-    <declare-styleable name="PagedIndicator">
-        <!-- Color used to draw dots -->
-        <attr name="indicatorDotColor" format="color" />
-    </declare-styleable>
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 1ef918d..8788557 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -67,7 +67,8 @@
     <color name="folder_preview_dark">#464746</color>
 
     <color name="folder_dot_color">?attr/colorPrimary</color>
-    <color name="folder_pagination_color">#ff006c5f</color>
+    <color name="folder_pagination_color_light">#ff006c5f</color>
+    <color name="folder_pagination_color_dark">#ffbfebe3</color>
 
     <color name="text_color_primary_dark">#FFFFFFFF</color>
     <color name="text_color_secondary_dark">#FFFFFFFF</color>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 01689e4..65d215f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -50,6 +50,7 @@
         <item name="workspaceStatusBarScrim">@drawable/workspace_bg</item>
         <item name="widgetsTheme">@style/WidgetContainerTheme</item>
         <item name="folderDotColor">@color/folder_dot_color</item>
+        <item name="folderPaginationColor">@color/folder_pagination_color_light</item>
         <item name="folderPreviewColor">@color/folder_preview_light</item>
         <item name="folderBackgroundColor">@color/folder_background_light</item>
         <item name="folderIconBorderColor">?android:attr/colorPrimary</item>
@@ -103,6 +104,7 @@
         <item name="popupShadeThird">@color/popup_shade_third_dark</item>
         <item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item>
         <item name="folderDotColor">@color/folder_dot_color</item>
+        <item name="folderPaginationColor">@color/folder_pagination_color_dark</item>
         <item name="folderPreviewColor">@color/folder_preview_dark</item>
         <item name="folderBackgroundColor">@color/folder_background_dark</item>
         <item name="folderIconBorderColor">?android:attr/colorPrimary</item>
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 5c0fd47..22b07ef 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -85,6 +85,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.Build;
@@ -1351,6 +1352,10 @@
 
         if (SHOW_DOT_PAGINATION.get()) {
             mWorkspace.getPageIndicator().setShouldAutoHide(true);
+            mWorkspace.getPageIndicator().setPaintColor(
+                    Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)
+                            ? Color.BLACK
+                            : Color.WHITE);
         }
     }
 
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 26ad4b5..62e7ef3 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -153,8 +153,8 @@
         Interpolator workspaceFadeInterpolator = config.getInterpolator(ANIM_WORKSPACE_FADE,
                 pageAlphaProvider.interpolator);
         float workspacePageIndicatorAlpha = (elements & WORKSPACE_PAGE_INDICATOR) != 0 ? 1 : 0;
-        mLauncher.getWorkspace().getPageIndicator().setAlpha(
-                propertySetter, workspacePageIndicatorAlpha, workspaceFadeInterpolator);
+        propertySetter.setViewAlpha(mLauncher.getWorkspace().getPageIndicator(),
+                workspacePageIndicatorAlpha, workspaceFadeInterpolator);
         Interpolator hotseatFadeInterpolator = config.getInterpolator(ANIM_HOTSEAT_FADE,
                 workspaceFadeInterpolator);
         float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index 9fe3c0b..d43731b 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -45,7 +45,7 @@
 import com.android.launcher3.keyboard.ViewGroupFocusHelper;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.pageindicators.LauncherDotsPageIndicator;
+import com.android.launcher3.pageindicators.PageIndicatorDots;
 import com.android.launcher3.touch.ItemClickHandler;
 import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
 import com.android.launcher3.util.Thunk;
@@ -60,7 +60,7 @@
 import java.util.function.ToIntFunction;
 import java.util.stream.Collectors;
 
-public class FolderPagedView extends PagedView<LauncherDotsPageIndicator> implements ClipPathView {
+public class FolderPagedView extends PagedView<PageIndicatorDots> implements ClipPathView {
 
     private static final String TAG = "FolderPagedView";
 
diff --git a/src/com/android/launcher3/pageindicators/LauncherDotsPageIndicator.java b/src/com/android/launcher3/pageindicators/LauncherDotsPageIndicator.java
deleted file mode 100644
index 8a21d13..0000000
--- a/src/com/android/launcher3/pageindicators/LauncherDotsPageIndicator.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2023 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.pageindicators;
-
-import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
-
-import android.animation.ObjectAnimator;
-import android.animation.TimeInterpolator;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.ViewConfiguration;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.Alarm;
-import com.android.launcher3.Insettable;
-import com.android.launcher3.anim.PropertySetter;
-import com.android.launcher3.util.MultiValueAlpha;
-
-/**
- * Extension of {@link PageIndicatorDots} with Launcher specific page-indicator functionality
- */
-public class LauncherDotsPageIndicator extends PageIndicatorDots
-        implements Insettable, PageIndicator {
-
-    private static final int PAGINATION_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay();
-    private static final int PAGINATION_FADE_IN_DURATION = 83;
-    private static final int PAGINATION_FADE_OUT_DURATION = 167;
-
-    private static final int INDEX_VIEW_ALPHA = 0;
-    private static final int INDEX_AUTO_HIDE = 1;
-    private static final int ALPHA_CHANNEL_COUNT = 2;
-
-    private final Alarm mAutoHideAlarm;
-    private final MultiValueAlpha mMultiValueAlpha;
-
-    private @Nullable ObjectAnimator mAlphaAnimator;
-    private boolean mShouldAutoHide;
-    private float mTargetAutoHideAlpha;
-
-    private boolean mIsSettled = true;
-    private int mTotalScroll;
-
-    public LauncherDotsPageIndicator(Context context) {
-        this(context, null);
-    }
-
-    public LauncherDotsPageIndicator(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public LauncherDotsPageIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        mMultiValueAlpha = new MultiValueAlpha(this, ALPHA_CHANNEL_COUNT);
-        mMultiValueAlpha.setUpdateVisibility(true);
-
-        mTargetAutoHideAlpha = mMultiValueAlpha.get(INDEX_AUTO_HIDE).getValue();
-
-        mAutoHideAlarm = new Alarm();
-        mAutoHideAlarm.setOnAlarmListener(a -> animatePaginationToAlpha(0));
-    }
-
-    @Override
-    public void setScroll(int currentScroll, int totalScroll) {
-        mTotalScroll = totalScroll;
-        super.setScroll(currentScroll, totalScroll);
-    }
-
-    @Override
-    public void setShouldAutoHide(boolean shouldAutoHide) {
-        mShouldAutoHide = shouldAutoHide;
-        mAutoHideAlarm.cancelAlarm();
-        if (!mIsSettled || !mShouldAutoHide) {
-            animatePaginationToAlpha(1);
-        } else {
-            mAutoHideAlarm.setAlarm(PAGINATION_FADE_DELAY);
-        }
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        if (mShouldAutoHide && mTotalScroll == 0) {
-            return;
-        }
-        super.onDraw(canvas);
-    }
-
-    @Override
-    public void setActiveMarker(int activePage) {
-        super.setActiveMarker(activePage);
-    }
-
-    @Override
-    public void setMarkersCount(int numMarkers) {
-        super.setMarkersCount(numMarkers);
-    }
-
-    @Override
-    public void pauseAnimations() {
-        if (mAlphaAnimator != null) {
-            mAlphaAnimator.pause();
-        }
-    }
-
-    @Override
-    public void skipAnimationsToEnd() {
-        if (mAlphaAnimator != null) {
-            mAlphaAnimator.end();
-        }
-    }
-
-    @Override
-    protected void onAnimationStateChanged(boolean isSettled) {
-        mIsSettled = isSettled;
-        if (!mShouldAutoHide) {
-            return;
-        }
-        mAutoHideAlarm.cancelAlarm();
-        if (isSettled) {
-            mAutoHideAlarm.setAlarm(PAGINATION_FADE_DELAY);
-        } else {
-            animatePaginationToAlpha(1f);
-        }
-    }
-
-    private void animatePaginationToAlpha(float targetAlpha) {
-        if (mTargetAutoHideAlpha == targetAlpha) {
-            // Ignore the new animation if it is going to the same alpha as the current animation.
-            return;
-        }
-
-        if (mAlphaAnimator != null) {
-            mAlphaAnimator.cancel();
-        }
-        mAlphaAnimator = ObjectAnimator.ofFloat(mMultiValueAlpha.get(INDEX_AUTO_HIDE),
-                MULTI_PROPERTY_VALUE, targetAlpha);
-        // If we are animating to decrease the alpha, then it's a fade out animation
-        // whereas if we are animating to increase the alpha, it's a fade in animation.
-        mAlphaAnimator.setDuration(targetAlpha == 0
-                ? PAGINATION_FADE_OUT_DURATION
-                : PAGINATION_FADE_IN_DURATION);
-        mAlphaAnimator.addListener(forEndCallback(() -> mAlphaAnimator = null));
-        mAlphaAnimator.start();
-        mTargetAutoHideAlpha = targetAlpha;
-    }
-
-
-    @Override
-    public void stopAllAnimations() {
-        super.stopAllAnimations();
-    }
-
-    @Override
-    public void prepareEntryAnimation() {
-        super.prepareEntryAnimation();
-    }
-
-    @Override
-    public void playEntryAnimation() {
-        super.playEntryAnimation();
-    }
-
-    /**
-     * We need to override setInsets to prevent InsettableFrameLayout from applying different
-     * margins on the pagination.
-     */
-    @Override
-    public void setInsets(Rect insets) {
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        return false;
-    }
-
-    @Override
-    public void setAlpha(PropertySetter setter, float alpha, TimeInterpolator interpolator) {
-        setter.setFloat(mMultiValueAlpha.get(INDEX_VIEW_ALPHA),
-                MULTI_PROPERTY_VALUE, alpha, interpolator);
-    }
-}
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index 193f50d..570d6ff 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -15,11 +15,6 @@
  */
 package com.android.launcher3.pageindicators;
 
-import android.animation.TimeInterpolator;
-import android.view.View;
-
-import com.android.launcher3.anim.PropertySetter;
-
 /**
  * Base class for a page indicator.
  */
@@ -53,9 +48,9 @@
     }
 
     /**
-     * Sets the provided alpha on the pageIndicator
+     * Sets the paint color.
      */
-    default void setAlpha(PropertySetter setter, float alpha, TimeInterpolator interpolator) {
-        setter.setViewAlpha((View) this, alpha, interpolator);
+    default void setPaintColor(int color) {
+        // No-op by default
     }
 }
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index 95452b9..b2c64b3 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -25,30 +25,42 @@
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
-import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.Paint.Style;
+import android.graphics.Rect;
 import android.graphics.RectF;
+import android.os.Handler;
+import android.os.Looper;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
+import android.util.IntProperty;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewOutlineProvider;
 import android.view.animation.Interpolator;
 import android.view.animation.OvershootInterpolator;
 
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.util.Themes;
 
 /**
  * {@link PageIndicator} which shows dots per page. The active page is shown with the current
  * accent color.
  */
-public class PageIndicatorDots extends View {
+public class PageIndicatorDots extends View implements Insettable, PageIndicator {
 
     private static final float SHIFT_PER_ANIMATION = 0.5f;
     private static final float SHIFT_THRESHOLD = 0.1f;
     private static final long ANIMATION_DURATION = 150;
+    private static final int PAGINATION_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay();
+    private static final int PAGINATION_FADE_IN_DURATION = 83;
+    private static final int PAGINATION_FADE_OUT_DURATION = 167;
 
     private static final int ENTER_ANIMATION_START_DELAY = 300;
     private static final int ENTER_ANIMATION_STAGGERED_DELAY = 150;
@@ -58,6 +70,9 @@
     private static final int DOT_ALPHA = 128;
     private static final float DOT_ALPHA_FRACTION = 0.5f;
     private static final int DOT_GAP_FACTOR = SHOW_DOT_PAGINATION.get() ? 4 : 3;
+    private static final int VISIBLE_ALPHA = 255;
+    private static final int INVISIBLE_ALPHA = 0;
+    private Paint mPaginationPaint;
 
     // This value approximately overshoots to 1.5 times the original size.
     private static final float ENTER_ANIMATION_OVERSHOOT_TENSION = 4.9f;
@@ -79,14 +94,30 @@
                 }
     };
 
+    private static final IntProperty<PageIndicatorDots> PAGINATION_ALPHA =
+            new IntProperty<PageIndicatorDots>("pagination_alpha") {
+        @Override
+        public Integer get(PageIndicatorDots obj) {
+            return obj.mPaginationPaint.getAlpha();
+        }
+
+        @Override
+        public void setValue(PageIndicatorDots obj, int alpha) {
+            obj.mPaginationPaint.setAlpha(alpha);
+            obj.invalidate();
+        }
+    };
+
+    private final Handler mDelayedPaginationFadeHandler = new Handler(Looper.getMainLooper());
     private final float mDotRadius;
     private final float mCircleGap;
     private final boolean mIsRtl;
 
-    private final Paint mPaginationPaint;
-
     private int mNumPages;
     private int mActivePage;
+    private int mTotalScroll;
+    private boolean mShouldAutoHide;
+    private int mToAlpha;
 
     /**
      * The current position of the active dot including the animation progress.
@@ -100,9 +131,13 @@
     private float mCurrentPosition;
     private float mFinalPosition;
     private ObjectAnimator mAnimator;
+    private @Nullable ObjectAnimator mAlphaAnimator;
 
     private float[] mEntryAnimationRadiusFactors;
 
+    private final Runnable mHidePaginationRunnable =
+            () -> animatePaginationToAlpha(INVISIBLE_ALPHA);
+
     public PageIndicatorDots(Context context) {
         this(context, null);
     }
@@ -116,34 +151,37 @@
 
         mPaginationPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mPaginationPaint.setStyle(Style.FILL);
-
-        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PagedIndicator);
-        mPaginationPaint.setColor(ta.getColor(R.styleable.PagedIndicator_indicatorDotColor, 0));
-        ta.recycle();
-
+        mPaginationPaint.setColor(Themes.getAttrColor(context, R.attr.folderPaginationColor));
         mDotRadius = (SHOW_DOT_PAGINATION.get()
                 ? getResources().getDimension(R.dimen.page_indicator_dot_size_v2)
                 : getResources().getDimension(R.dimen.page_indicator_dot_size))
                 / 2;
         mCircleGap = DOT_GAP_FACTOR * mDotRadius;
         setOutlineProvider(new MyOutlineProver());
-        mIsRtl = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+        mIsRtl = Utilities.isRtl(getResources());
     }
 
+    @Override
     public void setScroll(int currentScroll, int totalScroll) {
         if (SHOW_DOT_PAGINATION.get() && mActivePage != 0 && currentScroll == 0) {
             CURRENT_POSITION.set(this, (float) mActivePage);
             return;
         }
 
-        if (mNumPages <= 1 || totalScroll == 0) {
+        if (mNumPages <= 1) {
             return;
         }
 
+        if (mShouldAutoHide) {
+            animatePaginationToAlpha(VISIBLE_ALPHA);
+        }
+
         if (mIsRtl) {
             currentScroll = totalScroll - currentScroll;
         }
 
+        mTotalScroll = totalScroll;
+
         int scrollPerPage = totalScroll / (mNumPages - 1);
         int pageToLeft = scrollPerPage == 0 ? 0 : currentScroll / scrollPerPage;
         int pageToLeftScroll = pageToLeft * scrollPerPage;
@@ -153,12 +191,87 @@
         if (currentScroll < pageToLeftScroll + scrollThreshold) {
             // scroll is within the left page's threshold
             animateToPosition(pageToLeft);
+            if (mShouldAutoHide) {
+                hideAfterDelay();
+            }
         } else if (currentScroll > pageToRightScroll - scrollThreshold) {
             // scroll is far enough from left page to go to the right page
             animateToPosition(pageToLeft + 1);
+            if (mShouldAutoHide) {
+                hideAfterDelay();
+            }
         } else {
             // scroll is between left and right page
             animateToPosition(pageToLeft + SHIFT_PER_ANIMATION);
+            if (mShouldAutoHide) {
+                mDelayedPaginationFadeHandler.removeCallbacksAndMessages(null);
+            }
+        }
+    }
+
+    @Override
+    public void setShouldAutoHide(boolean shouldAutoHide) {
+        mShouldAutoHide = shouldAutoHide && SHOW_DOT_PAGINATION.get();
+        if (shouldAutoHide && mPaginationPaint.getAlpha() > INVISIBLE_ALPHA) {
+            hideAfterDelay();
+        } else if (!shouldAutoHide) {
+            mDelayedPaginationFadeHandler.removeCallbacksAndMessages(null);
+        }
+    }
+
+    @Override
+    public void setPaintColor(int color) {
+        mPaginationPaint.setColor(color);
+    }
+
+    private void hideAfterDelay() {
+        mDelayedPaginationFadeHandler.removeCallbacksAndMessages(null);
+        mDelayedPaginationFadeHandler.postDelayed(mHidePaginationRunnable, PAGINATION_FADE_DELAY);
+    }
+
+    private void animatePaginationToAlpha(int alpha) {
+        if (alpha == mToAlpha) {
+            // Ignore the new animation if it is going to the same alpha as the current animation.
+            return;
+        }
+
+        if (mAlphaAnimator != null) {
+            mAlphaAnimator.cancel();
+        }
+        mAlphaAnimator = ObjectAnimator.ofInt(this, PAGINATION_ALPHA,
+                alpha);
+        // If we are animating to decrease the alpha, then it's a fade out animation
+        // whereas if we are animating to increase the alpha, it's a fade in animation.
+        mAlphaAnimator.setDuration(alpha < mToAlpha
+                ? PAGINATION_FADE_OUT_DURATION
+                : PAGINATION_FADE_IN_DURATION);
+        mAlphaAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mAlphaAnimator = null;
+            }
+        });
+        mAlphaAnimator.start();
+        mToAlpha = alpha;
+    }
+
+    /**
+     * Pauses all currently running animations.
+     */
+    @Override
+    public void pauseAnimations() {
+        if (mAlphaAnimator != null) {
+            mAlphaAnimator.pause();
+        }
+    }
+
+    /**
+     * Force-ends all currently running or paused animations.
+     */
+    @Override
+    public void skipAnimationsToEnd() {
+        if (mAlphaAnimator != null) {
+            mAlphaAnimator.end();
         }
     }
 
@@ -168,25 +281,15 @@
             mCurrentPosition = mFinalPosition;
         }
         if (mAnimator == null && Float.compare(mCurrentPosition, mFinalPosition) != 0) {
-            onAnimationStateChanged(false);
             float positionForThisAnim = mCurrentPosition > mFinalPosition ?
                     mCurrentPosition - SHIFT_PER_ANIMATION : mCurrentPosition + SHIFT_PER_ANIMATION;
             mAnimator = ObjectAnimator.ofFloat(this, CURRENT_POSITION, positionForThisAnim);
             mAnimator.addListener(new AnimationCycleListener());
             mAnimator.setDuration(ANIMATION_DURATION);
             mAnimator.start();
-        } else if (mAnimator == null) {
-            // The state is only settled if the indicator lands on a int value
-            onAnimationStateChanged(Float.compare(Math.round(mFinalPosition), mFinalPosition) == 0);
         }
     }
 
-    /**
-     * Called when the animation state of the page indicator changes.
-     * @param isSettled true if the page indicator has settled at its final position
-     */
-    protected void onAnimationStateChanged(boolean isSettled) { }
-
     public void stopAllAnimations() {
         if (mAnimator != null) {
             mAnimator.cancel();
@@ -242,10 +345,14 @@
         animSet.start();
     }
 
+    @Override
     public void setActiveMarker(int activePage) {
-        mActivePage = activePage;
+        if (mActivePage != activePage) {
+            mActivePage = activePage;
+        }
     }
 
+    @Override
     public void setMarkersCount(int numMarkers) {
         mNumPages = numMarkers;
         requestLayout();
@@ -267,6 +374,11 @@
             return;
         }
 
+        if (mShouldAutoHide && mTotalScroll == 0) {
+            mPaginationPaint.setAlpha(INVISIBLE_ALPHA);
+            return;
+        }
+
         // Draw all page indicators;
         float circleGap = mCircleGap;
         float startX = (getWidth() - (mNumPages * circleGap) + mDotRadius) / 2;
@@ -368,9 +480,20 @@
         @Override
         public void onAnimationEnd(Animator animation) {
             if (!mCancelled) {
+                if (mShouldAutoHide && SHOW_DOT_PAGINATION.get()) {
+                    hideAfterDelay();
+                }
                 mAnimator = null;
                 animateToPosition(mFinalPosition);
             }
         }
     }
+
+    /**
+     * We need to override setInsets to prevent InsettableFrameLayout from applying different
+     * margins on the pagination.
+     */
+    @Override
+    public void setInsets(Rect insets) {
+    }
 }