Updating the fast scroll bar UI

Bug: 37015359
Change-Id: Iec0748f04ebe9a3eef13ff759da3cab6ff28c3a1
diff --git a/src/com/android/launcher3/BaseRecyclerView.java b/src/com/android/launcher3/BaseRecyclerView.java
index 514cc07..84358ea 100644
--- a/src/com/android/launcher3/BaseRecyclerView.java
+++ b/src/com/android/launcher3/BaseRecyclerView.java
@@ -185,13 +185,6 @@
     }
 
     /**
-     * Returns the track color (ignoring alpha), can be overridden by each subclass.
-     */
-    public int getFastScrollerTrackColor(int defaultTrackColor) {
-        return defaultTrackColor;
-    }
-
-    /**
      * Returns the scrollbar for this recycler view.
      */
     public BaseRecyclerViewFastScrollBar getScrollBar() {
diff --git a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
index 3039744..9e8d300 100644
--- a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
+++ b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
@@ -29,6 +29,7 @@
 import android.widget.TextView;
 
 import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.graphics.FastScrollThumbDrawable;
 import com.android.launcher3.util.Themes;
 
 /**
@@ -52,7 +53,7 @@
 
     private final static int MAX_TRACK_ALPHA = 30;
     private final static int SCROLL_BAR_VIS_DURATION = 150;
-    private static final float FAST_SCROLL_OVERLAY_Y_OFFSET_FACTOR = 1.5f;
+    private static final float FAST_SCROLL_OVERLAY_Y_OFFSET_FACTOR = 0.75f;
 
     private final Rect mTmpRect = new Rect();
     private final BaseRecyclerView mRv;
@@ -64,12 +65,12 @@
 
     private final int mMinWidth;
     private final int mMaxWidth;
+    private final int mThumbPadding;
 
     // Current width of the track
     private int mWidth;
     private ObjectAnimator mWidthAnimator;
 
-    private final Path mThumbPath = new Path();
     private final Paint mThumbPaint;
     private final int mThumbHeight;
 
@@ -94,7 +95,7 @@
     public BaseRecyclerViewFastScrollBar(BaseRecyclerView rv, Resources res) {
         mRv = rv;
         mTrackPaint = new Paint();
-        mTrackPaint.setColor(rv.getFastScrollerTrackColor(Color.BLACK));
+        mTrackPaint.setColor(Themes.getAttrColor(rv.getContext(), android.R.attr.textColorPrimary));
         mTrackPaint.setAlpha(MAX_TRACK_ALPHA);
 
         mThumbPaint = new Paint();
@@ -102,16 +103,19 @@
         mThumbPaint.setColor(Themes.getColorAccent(rv.getContext()));
         mThumbPaint.setStyle(Paint.Style.FILL);
 
-        mWidth = mMinWidth = res.getDimensionPixelSize(R.dimen.container_fastscroll_thumb_min_width);
-        mMaxWidth = res.getDimensionPixelSize(R.dimen.container_fastscroll_thumb_max_width);
-        mThumbHeight = res.getDimensionPixelSize(R.dimen.container_fastscroll_thumb_height);
-        mTouchInset = res.getDimensionPixelSize(R.dimen.container_fastscroll_thumb_touch_inset);
+        mWidth = mMinWidth = res.getDimensionPixelSize(R.dimen.fastscroll_track_min_width);
+        mMaxWidth = res.getDimensionPixelSize(R.dimen.fastscroll_track_max_width);
+
+        mThumbPadding = res.getDimensionPixelSize(R.dimen.fastscroll_thumb_padding);
+        mThumbHeight = res.getDimensionPixelSize(R.dimen.fastscroll_thumb_height);
+
+        mTouchInset = res.getDimensionPixelSize(R.dimen.fastscroll_thumb_touch_inset);
         mIsRtl = Utilities.isRtl(res);
-        updateThumbPath();
     }
 
     public void setPopupView(View popup) {
         mPopupView = (TextView) popup;
+        mPopupView.setBackground(new FastScrollThumbDrawable(mThumbPaint, mIsRtl));
     }
 
     public void setDetachThumbOnFastScroll() {
@@ -154,24 +158,6 @@
         mRv.invalidate(left, top, left + mMaxWidth, top + mRv.getScrollbarTrackHeight());
 
         mWidth = width;
-        updateThumbPath();
-    }
-
-    /**
-     * Updates the path for the thumb drawable.
-     */
-    private void updateThumbPath() {
-        int smallWidth = mIsRtl ? mWidth : -mWidth;
-        int largeWidth = mIsRtl ? mMaxWidth : -mMaxWidth;
-
-        mThumbPath.reset();
-        mThumbPath.moveTo(0, 0);
-        mThumbPath.lineTo(0, mThumbHeight);             // Left edge
-        mThumbPath.lineTo(smallWidth, mThumbHeight);    // bottom edge
-        mThumbPath.cubicTo(smallWidth, mThumbHeight,    // right edge
-                largeWidth, mThumbHeight / 2,
-                smallWidth, 0);
-        mThumbPath.close();
     }
 
     public int getThumbHeight() {
@@ -265,15 +251,16 @@
         }
         int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
         if (!mIsRtl) {
-            canvas.translate(mRv.getWidth(), 0);
+            canvas.translate(mRv.getWidth() - mWidth, 0);
         }
         canvas.translate(0, mRv.getPaddingTop());
         // Draw the track
-        int thumbWidth = mIsRtl ? mWidth : -mWidth;
-        canvas.drawRect(0, 0, thumbWidth, mRv.getScrollbarTrackHeight(), mTrackPaint);
+        canvas.drawRoundRect(0, 0, mWidth, mRv.getScrollbarTrackHeight(),
+                mWidth, mWidth, mTrackPaint);
 
-        canvas.translate(0, mThumbOffsetY);
-        canvas.drawPath(mThumbPath, mThumbPaint);
+        canvas.translate(-mThumbPadding, mThumbOffsetY);
+        float r = mWidth + mThumbPadding + mThumbPadding;
+        canvas.drawRoundRect(0, 0, r, mThumbHeight, r, r, mThumbPaint);
         canvas.restoreToCount(saveCount);
     }
 
@@ -320,7 +307,8 @@
     private void updatePopupY(int lastTouchY) {
         int height = mPopupView.getHeight();
         float top = lastTouchY - (FAST_SCROLL_OVERLAY_Y_OFFSET_FACTOR * height);
-        top = Math.max(mMaxWidth, Math.min(top, mRv.getScrollbarTrackHeight() - mMaxWidth - height));
+        top = Utilities.boundToRange(top,
+                mMaxWidth, mRv.getScrollbarTrackHeight() - mMaxWidth - height);
         mPopupView.setTranslationY(top);
     }
 }
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index b2a74ff..0607a1e 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -376,7 +376,8 @@
         if (position == NO_POSITION) {
             return -1;
         }
-        return getCurrentScrollY(position, getLayoutManager().getDecoratedTop(child));
+        return getPaddingTop() +
+                getCurrentScrollY(position, getLayoutManager().getDecoratedTop(child));
     }
 
     public int getCurrentScrollY(int position, int offset) {
@@ -406,8 +407,7 @@
             }
             mCachedScrollPositions.put(position, y);
         }
-
-        return getPaddingTop() + y - offset;
+        return y - offset;
     }
 
     /**
@@ -416,7 +416,7 @@
      */
     @Override
     protected int getAvailableScrollHeight() {
-        return getCurrentScrollY(mApps.getAdapterItems().size(), 0)
+        return getPaddingTop() + getCurrentScrollY(mApps.getAdapterItems().size(), 0)
                 - getHeight() + getPaddingBottom();
     }
 
diff --git a/src/com/android/launcher3/graphics/FastScrollThumbDrawable.java b/src/com/android/launcher3/graphics/FastScrollThumbDrawable.java
new file mode 100644
index 0000000..6ebc74e
--- /dev/null
+++ b/src/com/android/launcher3/graphics/FastScrollThumbDrawable.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.graphics;
+
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Outline;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+
+public class FastScrollThumbDrawable extends Drawable {
+
+    private static final Matrix sMatrix = new Matrix();
+
+    private final Path mPath = new Path();
+    private final Paint mPaint;
+    private final boolean mIsRtl;
+
+    public FastScrollThumbDrawable(Paint paint, boolean isRtl) {
+        mPaint = paint;
+        mIsRtl = isRtl;
+    }
+
+    @Override
+    public void getOutline(Outline outline) {
+        if (mPath.isConvex()) {
+            outline.setConvexPath(mPath);
+        }
+    }
+
+    @Override
+    protected void onBoundsChange(Rect bounds) {
+        mPath.reset();
+
+        float r = bounds.height()  * 0.5f;
+        // The path represents a rotate tear-drop shape, with radius of one corner is 1/5th of the
+        // other 3 corners.
+        float diameter = 2 * r;
+        float r2 = r / 5;
+        mPath.addRoundRect(bounds.left, bounds.top, bounds.left + diameter, bounds.top + diameter,
+                new float[] {r, r, r, r, r2, r2, r, r},
+                Path.Direction.CCW);
+
+        sMatrix.setRotate(-45, bounds.left + r, bounds.top + r);
+        if (mIsRtl) {
+            sMatrix.postTranslate(bounds.width(), 0);
+            sMatrix.postScale(-1, 1, bounds.width(), 0);
+        }
+        mPath.transform(sMatrix);
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        canvas.drawPath(mPath, mPaint);
+    }
+
+    @Override
+    public void setAlpha(int i) {
+        // Not supported
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter colorFilter) {
+        // Not supported
+    }
+
+    @Override
+    public int getOpacity() {
+        return PixelFormat.TRANSLUCENT;
+    }
+}
diff --git a/src/com/android/launcher3/widget/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/WidgetsRecyclerView.java
index f47ca3eeb..9730a82 100644
--- a/src/com/android/launcher3/widget/WidgetsRecyclerView.java
+++ b/src/com/android/launcher3/widget/WidgetsRecyclerView.java
@@ -59,10 +59,6 @@
         setLayoutManager(new LinearLayoutManager(getContext()));
     }
 
-    public int getFastScrollerTrackColor(int defaultTrackColor) {
-        return Color.WHITE;
-    }
-
     @Override
     public void setAdapter(Adapter adapter) {
         super.setAdapter(adapter);