Fixes for fast-scrollbar when using work profile tabs in all apps.

- do not hide scrollbar between switching tabs
- full scrollbar height
- show predictionrow only when fully scrolled to top

Bug: 70037972
Bug: 68713881

Change-Id: Icaa434ce2726b75d22ec4ac3287ab2b0e18ce42b
diff --git a/res/layout-land/all_apps_fast_scroller.xml b/res/layout-land/all_apps_fast_scroller.xml
index 6a68f84..16aa2af 100644
--- a/res/layout-land/all_apps_fast_scroller.xml
+++ b/res/layout-land/all_apps_fast_scroller.xml
@@ -21,7 +21,7 @@
         android:id="@+id/fast_scroller_popup"
         style="@style/FastScrollerPopup"
         android:layout_alignParentEnd="true"
-        android:layout_alignTop="@+id/apps_list_view"
+        android:layout_below="@+id/search_container_all_apps"
         android:layout_marginTop="-5dp"
         android:layout_marginEnd="-45dp" />
 
@@ -31,7 +31,7 @@
         android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
         android:layout_alignParentEnd="true"
-        android:layout_alignParentTop="@+id/apps_list_view"
+        android:layout_below="@+id/search_container_all_apps"
         android:layout_marginEnd="-88dp"
         android:layout_marginTop="14dp"
         launcher:canThumbDetach="true" />
diff --git a/res/layout-sw720dp/all_apps_fast_scroller.xml b/res/layout-sw720dp/all_apps_fast_scroller.xml
index 12c15cc..5537bc6 100644
--- a/res/layout-sw720dp/all_apps_fast_scroller.xml
+++ b/res/layout-sw720dp/all_apps_fast_scroller.xml
@@ -21,7 +21,7 @@
         android:id="@+id/fast_scroller_popup"
         style="@style/FastScrollerPopup"
         android:layout_alignParentEnd="true"
-        android:layout_alignTop="@+id/apps_list_view"
+        android:layout_below="@+id/search_container_all_apps"
         android:layout_marginEnd="@dimen/fastscroll_popup_margin" />
 
     <com.android.launcher3.views.RecyclerViewFastScroller
@@ -30,7 +30,7 @@
         android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
         android:layout_alignParentEnd="true"
-        android:layout_alignTop="@+id/apps_list_view"
+        android:layout_below="@+id/search_container_all_apps"
         android:layout_marginEnd="@dimen/fastscroll_end_margin"
         launcher:canThumbDetach="true" />
 
diff --git a/res/layout/all_apps_fast_scroller.xml b/res/layout/all_apps_fast_scroller.xml
index 12c15cc..5537bc6 100644
--- a/res/layout/all_apps_fast_scroller.xml
+++ b/res/layout/all_apps_fast_scroller.xml
@@ -21,7 +21,7 @@
         android:id="@+id/fast_scroller_popup"
         style="@style/FastScrollerPopup"
         android:layout_alignParentEnd="true"
-        android:layout_alignTop="@+id/apps_list_view"
+        android:layout_below="@+id/search_container_all_apps"
         android:layout_marginEnd="@dimen/fastscroll_popup_margin" />
 
     <com.android.launcher3.views.RecyclerViewFastScroller
@@ -30,7 +30,7 @@
         android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
         android:layout_alignParentEnd="true"
-        android:layout_alignTop="@+id/apps_list_view"
+        android:layout_below="@+id/search_container_all_apps"
         android:layout_marginEnd="@dimen/fastscroll_end_margin"
         launcher:canThumbDetach="true" />
 
diff --git a/src/com/android/launcher3/BaseRecyclerView.java b/src/com/android/launcher3/BaseRecyclerView.java
index b315980..bce0e2e 100644
--- a/src/com/android/launcher3/BaseRecyclerView.java
+++ b/src/com/android/launcher3/BaseRecyclerView.java
@@ -68,6 +68,7 @@
         ViewGroup parent = (ViewGroup) getParent().getParent();
         mScrollbar = parent.findViewById(R.id.fast_scroller);
         mScrollbar.setRecyclerView(this, parent.findViewById(R.id.fast_scroller_popup));
+        onUpdateScrollbar(0);
     }
 
     /**
@@ -112,7 +113,7 @@
      * Returns the height of the fast scroll bar
      */
     public int getScrollbarTrackHeight() {
-        return getHeight() - getScrollBarTop() - getPaddingBottom();
+        return mScrollbar.getHeight() - getScrollBarTop() - getPaddingBottom();
     }
 
     /**
@@ -130,12 +131,6 @@
         return availableScrollBarHeight;
     }
 
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        onUpdateScrollbar(0);
-        super.dispatchDraw(canvas);
-    }
-
     /**
      * Updates the scrollbar thumb offset to match the visible scroll of the recycler view.  It does
      * this by mapping the available scroll area of the recycler view to the available space for the
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 9ee9514..097bc5b 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -492,19 +492,9 @@
         mViewPager.setAdapter(mTabsPagerAdapter = new TabsPagerAdapter());
         mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
 
-            boolean mVisible = true;
-
             @Override
             public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                 tabs.updateIndicatorPosition(position, positionOffset);
-                if (positionOffset == 0 && !mVisible || positionOffset > 0 && mVisible) {
-                    mVisible = positionOffset == 0;
-                    for (int i = 0; i < mAH.length; i++) {
-                        if (mAH[i].recyclerView != null) {
-                            mAH[i].recyclerView.getScrollbar().setAlpha(mVisible ? 1 : 0);
-                        }
-                    }
-                }
             }
 
             @Override
@@ -521,6 +511,7 @@
             public void onPageScrollStateChanged(int state) {
             }
         });
+        mAH[AdapterHolder.MAIN].recyclerView.bindFastScrollbar();
 
         findViewById(R.id.tab_personal)
                 .setOnClickListener((View view) -> mViewPager.setCurrentItem(0));
@@ -568,8 +559,8 @@
             contentHeight += getResources()
                     .getDimensionPixelSize(R.dimen.all_apps_prediction_row_divider_height);
         }
-        RecyclerView mainRV = mAH[AdapterHolder.MAIN].recyclerView;
-        RecyclerView workRV = mAH[AdapterHolder.WORK].recyclerView;
+        AllAppsRecyclerView mainRV = mAH[AdapterHolder.MAIN].recyclerView;
+        AllAppsRecyclerView workRV = mAH[AdapterHolder.WORK].recyclerView;
         mFloatingHeaderHandler.setup(mainRV, workRV, contentHeight);
         mFloatingHeaderHandler.getContentView().setup(mAH[AdapterHolder.MAIN].adapter,
                 mComponentToAppMap, mNumPredictedAppsPerRow);
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 5789b67..fd80784 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -31,7 +31,6 @@
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.ItemInfo;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.anim.SpringAnimationHandler;
 import com.android.launcher3.config.FeatureFlags;
@@ -53,7 +52,6 @@
     private AlphabeticalAppsList mApps;
     private AllAppsFastScrollHelper mFastScrollHelper;
     private int mNumAppsPerRow;
-    private int mUserProfileTabContentHeight;
 
     // The specific view heights that we use to calculate scroll
     private SparseIntArray mViewHeights = new SparseIntArray();
@@ -127,8 +125,6 @@
     public void setApps(AlphabeticalAppsList apps, boolean usingTabs) {
         mApps = apps;
         mFastScrollHelper = new AllAppsFastScrollHelper(this, apps);
-        mUserProfileTabContentHeight = usingTabs
-                ? Launcher.getLauncher(getContext()).getDeviceProfile().allAppsCellHeightPx : 0;;
     }
 
     public AlphabeticalAppsList getApps() {
@@ -362,6 +358,9 @@
      */
     @Override
     public void onUpdateScrollbar(int dy) {
+        if (mApps == null) {
+            return;
+        }
         List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
 
         // Skip early if there are no items or we haven't been measured
@@ -488,18 +487,11 @@
     @Override
     protected int getAvailableScrollHeight() {
         return getPaddingTop() + getCurrentScrollY(getAdapter().getItemCount(), 0)
-                - getHeight() + getPaddingBottom() + mUserProfileTabContentHeight;
+                - getHeight() + getPaddingBottom();
     }
 
     public int getScrollBarTop() {
-        return super.getScrollBarTop() + mUserProfileTabContentHeight;
-    }
-
-    /**
-     * Returns the height of the fast scroll bar
-     */
-    public int getScrollbarTrackHeight() {
-        return super.getScrollbarTrackHeight() + mUserProfileTabContentHeight;
+        return getResources().getDimensionPixelOffset(R.dimen.all_apps_header_top_padding);
     }
 
     public RecyclerViewFastScroller getScrollbar() {
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderHandler.java b/src/com/android/launcher3/allapps/FloatingHeaderHandler.java
index c4b533b..b4685ea 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderHandler.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderHandler.java
@@ -30,6 +30,8 @@
 public class FloatingHeaderHandler extends RecyclerView.OnScrollListener
         implements ValueAnimator.AnimatorUpdateListener {
 
+    private static final boolean SHOW_PREDICTIONS_ONLY_ON_TOP = true;
+
     private final View mHeaderView;
     private final PredictionRowView mPredictionRow;
     private final ViewGroup mTabLayout;
@@ -37,8 +39,8 @@
     private final Rect mClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
     private final ValueAnimator mAnimator = ValueAnimator.ofInt(0, 0);
 
-    private RecyclerView mMainRV;
-    private RecyclerView mWorkRV;
+    private AllAppsRecyclerView mMainRV;
+    private AllAppsRecyclerView mWorkRV;
     private boolean mTopOnlyMode;
     private boolean mHeaderHidden;
     private int mMaxTranslation;
@@ -55,22 +57,25 @@
         mPredictionRow = header.findViewById(R.id.header_content);
     }
 
-    public void setup(@NonNull RecyclerView personalRV, @Nullable RecyclerView workRV,
+    public void setup(@NonNull AllAppsRecyclerView personalRV, @Nullable AllAppsRecyclerView workRV,
         int predictionRowHeight) {
         mTopOnlyMode = workRV == null;
         mTabLayout.setVisibility(mTopOnlyMode ? View.GONE : View.VISIBLE);
         mPredictionRow.getLayoutParams().height = predictionRowHeight;
         mMaxTranslation = predictionRowHeight;
-        mMainRV = personalRV;
-        mMainRV.addOnScrollListener(this);
-        mWorkRV = workRV;
-        if (workRV != null) {
-            workRV.addOnScrollListener(this);
-        }
+        mMainRV = setupRV(mMainRV, personalRV);
+        mWorkRV = setupRV(mWorkRV, workRV);
         setMainActive(true);
         setupDivider();
     }
 
+    private AllAppsRecyclerView setupRV(AllAppsRecyclerView old, AllAppsRecyclerView updated) {
+        if (old != updated && updated != null ) {
+            updated.addOnScrollListener(this);
+        }
+        return updated;
+    }
+
     private void setupDivider() {
         Resources res = mHeaderView.getResources();
         int verticalGap = res.getDimensionPixelSize(R.dimen.all_apps_divider_margin_vertical);
@@ -115,10 +120,9 @@
             mAnimator.cancel();
         }
 
-        int current = isMainRV
-                ? (mMainScrolledY -= dy)
-                : (mWorkScrolledY -= dy);
-
+        int current = - (isMainRV
+                ? mMainRV.getCurrentScrollY()
+                : mWorkRV.getCurrentScrollY());
         moved(current);
         apply();
     }
@@ -130,7 +134,8 @@
     }
 
     private boolean canSnapAt(int currentScrollY) {
-        return !mTopOnlyMode || Math.abs(currentScrollY) <= mPredictionRow.getHeight();
+        boolean snapOnlyOnTop = SHOW_PREDICTIONS_ONLY_ON_TOP || mTopOnlyMode;
+        return !snapOnlyOnTop || Math.abs(currentScrollY) <= mPredictionRow.getHeight();
     }
 
     private void moved(final int currentScrollY) {
@@ -179,6 +184,9 @@
 
     @Override
     public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+        if (SHOW_PREDICTIONS_ONLY_ON_TOP) {
+            return;
+        }
         if (!mTopOnlyMode && newState == RecyclerView.SCROLL_STATE_IDLE
                 && mTranslationY != -mMaxTranslation && mTranslationY != 0) {
             float scroll = Math.abs(getCurrentScroll());
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index 8f20a8d..b36a0ff 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -141,10 +141,11 @@
     }
 
     public void setRecyclerView(BaseRecyclerView rv, TextView popupView) {
-        mRv = rv;
-        if (mOnScrollListener != null) {
+        if (mRv != null && mOnScrollListener != null) {
             mRv.removeOnScrollListener(mOnScrollListener);
         }
+        mRv = rv;
+
         mRv.addOnScrollListener(mOnScrollListener = new RecyclerView.OnScrollListener() {
             @Override
             public void onScrolled(RecyclerView recyclerView, int dx, int dy) {