FloatingHeaderHandler refactored into custom view FloatingHeaderView.

No logical change.

Change-Id: I9a6dadb151872abe9915e96833af530ca08ddb8e
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index c42c15c..6e91095 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -31,7 +31,7 @@
 
     <include layout="@layout/all_apps_fast_scroller" />
 
-    <RelativeLayout
+    <com.android.launcher3.allapps.FloatingHeaderView
         android:id="@+id/all_apps_header"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
@@ -73,7 +73,7 @@
                 android:textColor="@color/all_apps_tab_text"
                 android:background="?android:attr/selectableItemBackground"/>
         </com.android.launcher3.views.SlidingTabStrip>
-    </RelativeLayout>
+    </com.android.launcher3.allapps.FloatingHeaderView>
 
     <!-- Note: we are reusing/repurposing a system attribute for search layout, because of a
      platform bug, which prevents using custom attributes in <include> tag -->
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 6684851..0c992ba 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -85,8 +85,7 @@
     private SearchUiManager mSearchUiManager;
     private View mSearchContainer;
     private InterceptingViewPager mViewPager;
-    private ViewGroup mHeader;
-    private FloatingHeaderHandler mFloatingHeaderHandler;
+    private FloatingHeaderView mHeader;
     private TabsPagerAdapter mTabsPagerAdapter;
 
     private SpannableStringBuilder mSearchQueryBuilder = null;
@@ -234,8 +233,8 @@
         for (int i = 0; i < mAH.length; i++) {
             updatePromiseAppProgress(app, mAH[i].recyclerView);
         }
-        if (mFloatingHeaderHandler != null) {
-            updatePromiseAppProgress(app, mFloatingHeaderHandler.getContentView());
+        if (isHeaderVisible()) {
+            updatePromiseAppProgress(app, mHeader.getPredictionRow());
         }
     }
 
@@ -286,8 +285,8 @@
                 mAH[i].recyclerView.scrollToTop();
             }
         }
-        if (mFloatingHeaderHandler != null) {
-            mFloatingHeaderHandler.reset();
+        if (isHeaderVisible()) {
+            mHeader.reset();
         }
         // Reset the search bar and base recycler view after transitioning home
         mSearchUiManager.reset();
@@ -309,7 +308,6 @@
         });
 
         mHeader = findViewById(R.id.all_apps_header);
-        mFloatingHeaderHandler = new FloatingHeaderHandler(mHeader);
         rebindAdapters(mUsingTabs);
 
         mSearchContainer = findViewById(R.id.search_container_all_apps);
@@ -447,7 +445,6 @@
             if (FeatureFlags.ALL_APPS_PREDICTION_ROW_VIEW) {
                 setupHeader();
             } else {
-                mFloatingHeaderHandler = null;
                 mHeader.setVisibility(View.GONE);
             }
         }
@@ -501,7 +498,7 @@
             @Override
             public void onPageSelected(int pos) {
                 tabs.updateTabTextColor(pos);
-                mFloatingHeaderHandler.setMainActive(pos == 0);
+                mHeader.setMainActive(pos == 0);
                 applyTouchDelegate();
                 if (mAH[pos].recyclerView != null) {
                     mAH[pos].recyclerView.bindFastScrollbar();
@@ -524,14 +521,16 @@
     }
 
     public void setPredictedApps(List<ComponentKeyMapper<AppInfo>> apps) {
-        if (mFloatingHeaderHandler != null) {
-            mFloatingHeaderHandler.getContentView().setPredictedApps(apps);
+        if (isHeaderVisible()) {
+            mHeader.getPredictionRow().setPredictedApps(apps);
         }
         mAH[AdapterHolder.MAIN].appsList.setPredictedApps(apps);
         boolean hasPredictions = !apps.isEmpty();
         if (mHasPredictions != hasPredictions) {
             mHasPredictions = hasPredictions;
-            setupHeader();
+            if (FeatureFlags.ALL_APPS_PREDICTION_ROW_VIEW) {
+                setupHeader();
+            }
         }
     }
 
@@ -547,12 +546,12 @@
         return mUsingTabs;
     }
 
-    public FloatingHeaderHandler getFloatingHeaderHandler() {
-        return mFloatingHeaderHandler;
+    public FloatingHeaderView getFloatingHeaderView() {
+        return mHeader;
     }
 
     private void setupHeader() {
-        if (mFloatingHeaderHandler == null) {
+        if (mHeader == null) {
             return;
         }
         mHeader.setVisibility(View.VISIBLE);
@@ -565,8 +564,8 @@
         }
         AllAppsRecyclerView mainRV = mAH[AdapterHolder.MAIN].recyclerView;
         AllAppsRecyclerView workRV = mAH[AdapterHolder.WORK].recyclerView;
-        mFloatingHeaderHandler.setup(mainRV, workRV, contentHeight);
-        mFloatingHeaderHandler.getContentView().setup(mAH[AdapterHolder.MAIN].adapter,
+        mHeader.setup(mainRV, workRV, contentHeight);
+        mHeader.getPredictionRow().setup(mAH[AdapterHolder.MAIN].adapter,
                 mComponentToAppMap, mNumPredictedAppsPerRow);
 
         int padding = contentHeight;
@@ -584,7 +583,7 @@
             mAH[i].adapter.setLastSearchQuery(query);
         }
         boolean hasQuery = !TextUtils.isEmpty(query);
-        if (mFloatingHeaderHandler != null && mUsingTabs && hasQuery) {
+        if (mUsingTabs && hasQuery) {
             mSearchModeWhileUsingTabs = true;
             rebindAdapters(false); // hide tabs
         } else if (mSearchModeWhileUsingTabs && !hasQuery) {
@@ -630,12 +629,16 @@
 
     public List<AppInfo> getPredictedApps() {
         if (mUsingTabs) {
-            return mFloatingHeaderHandler.getContentView().getPredictedApps();
+            return mHeader.getPredictionRow().getPredictedApps();
         } else {
             return mAH[AdapterHolder.MAIN].appsList.getPredictedApps();
         }
     }
 
+    private boolean isHeaderVisible() {
+        return mHeader != null && mHeader.getVisibility() == View.VISIBLE;
+    }
+
     public class AdapterHolder {
         public static final int MAIN = 0;
         public static final int WORK = 1;
@@ -685,8 +688,8 @@
                         ? paddingTopForTabs : padding.top;
                 recyclerView.setPadding(padding.left, paddingTop, padding.right, padding.bottom);
             }
-            if (mFloatingHeaderHandler != null) {
-                mFloatingHeaderHandler.getContentView()
+            if (isHeaderVisible()) {
+                mHeader.getPredictionRow()
                         .setPadding(padding.left, 0 , padding.right, 0);
             }
         }
@@ -698,8 +701,8 @@
                 }
                 adapter.setNumAppsPerRow(mNumAppsPerRow);
                 appsList.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow);
-                if (mFloatingHeaderHandler != null) {
-                    mFloatingHeaderHandler.getContentView()
+                if (isHeaderVisible()) {
+                    mHeader.getPredictionRow()
                             .setNumAppsPerRow(mNumPredictedAppsPerRow);
                 }
             }
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderHandler.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
similarity index 74%
rename from src/com/android/launcher3/allapps/FloatingHeaderHandler.java
rename to src/com/android/launcher3/allapps/FloatingHeaderView.java
index b4685ea..39e6818 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderHandler.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -15,30 +15,65 @@
  */
 package com.android.launcher3.allapps;
 
+
 import android.animation.ValueAnimator;
+import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.RelativeLayout;
 
 import com.android.launcher3.R;
 
-public class FloatingHeaderHandler extends RecyclerView.OnScrollListener
-        implements ValueAnimator.AnimatorUpdateListener {
+public class FloatingHeaderView extends RelativeLayout 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;
-    private final View mDivider;
     private final Rect mClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
     private final ValueAnimator mAnimator = ValueAnimator.ofInt(0, 0);
+    private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {
+        @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());
+                boolean expand =  scroll > mMaxTranslation
+                        ? Math.abs(mTranslationY) < mMaxTranslation / 2 : true;
+                setExpanded(expand);
+            }
+        }
 
+        @Override
+        public void onScrolled(RecyclerView rv, int dx, int dy) {
+            boolean isMainRV = rv == mMainRV;
+            if (isMainRV != mMainRVActive) {
+                return;
+            }
+
+            if (mAnimator.isStarted()) {
+                mAnimator.cancel();
+            }
+
+            int current = - (isMainRV
+                    ? mMainRV.getCurrentScrollY()
+                    : mWorkRV.getCurrentScrollY());
+            moved(current);
+            apply();
+        }
+    };
+
+    private PredictionRowView mPredictionRow;
+    private ViewGroup mTabLayout;
+    private View mDivider;
     private AllAppsRecyclerView mMainRV;
     private AllAppsRecyclerView mWorkRV;
     private boolean mTopOnlyMode;
@@ -50,15 +85,24 @@
     private int mWorkScrolledY;
     private boolean mMainRVActive;
 
-    public FloatingHeaderHandler(@NonNull ViewGroup header) {
-        mHeaderView = header;
-        mTabLayout = header.findViewById(R.id.tabs);
-        mDivider = header.findViewById(R.id.divider);
-        mPredictionRow = header.findViewById(R.id.header_content);
+    public FloatingHeaderView(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public FloatingHeaderView(@NonNull Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mTabLayout = findViewById(R.id.tabs);
+        mDivider = findViewById(R.id.divider);
+        mPredictionRow = findViewById(R.id.header_content);
     }
 
     public void setup(@NonNull AllAppsRecyclerView personalRV, @Nullable AllAppsRecyclerView workRV,
-        int predictionRowHeight) {
+                      int predictionRowHeight) {
         mTopOnlyMode = workRV == null;
         mTabLayout.setVisibility(mTopOnlyMode ? View.GONE : View.VISIBLE);
         mPredictionRow.getLayoutParams().height = predictionRowHeight;
@@ -71,13 +115,13 @@
 
     private AllAppsRecyclerView setupRV(AllAppsRecyclerView old, AllAppsRecyclerView updated) {
         if (old != updated && updated != null ) {
-            updated.addOnScrollListener(this);
+            updated.addOnScrollListener(mOnScrollListener);
         }
         return updated;
     }
 
     private void setupDivider() {
-        Resources res = mHeaderView.getResources();
+        Resources res = getResources();
         int verticalGap = res.getDimensionPixelSize(R.dimen.all_apps_divider_margin_vertical);
         int sideGap = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
         mDivider.setPadding(sideGap, verticalGap,sideGap, mTopOnlyMode ? verticalGap : 0);
@@ -93,11 +137,7 @@
         setExpanded(true);
     }
 
-    public View getHeaderView() {
-        return mHeaderView;
-    }
-
-    public PredictionRowView getContentView() {
+    public PredictionRowView getPredictionRow() {
         return mPredictionRow;
     }
 
@@ -109,24 +149,6 @@
         return mDivider;
     }
 
-    @Override
-    public void onScrolled(RecyclerView rv, int dx, int dy) {
-        boolean isMainRV = rv == mMainRV;
-        if (isMainRV != mMainRVActive) {
-            return;
-        }
-
-        if (mAnimator.isStarted()) {
-            mAnimator.cancel();
-        }
-
-        int current = - (isMainRV
-                ? mMainRV.getCurrentScrollY()
-                : mWorkRV.getCurrentScrollY());
-        moved(current);
-        apply();
-    }
-
     public void reset() {
         mMainScrolledY = 0;
         mWorkScrolledY = 0;
@@ -182,20 +204,6 @@
         }
     }
 
-    @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());
-            boolean expand =  scroll > mMaxTranslation
-                    ? Math.abs(mTranslationY) < mMaxTranslation / 2 : true;
-            setExpanded(expand);
-        }
-    }
-
     private void setExpanded(boolean expand) {
         int translateTo = expand ? 0 : -mMaxTranslation;
         mAnimator.setIntValues(mTranslationY, translateTo);
@@ -221,3 +229,5 @@
     }
 
 }
+
+