Merge "Fix UI overlapping and void space in the full widgets picker" into sc-dev am: bcf85de807

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/14442204

Change-Id: Ia17caafab186bc7e686256e56a51e83c1ad2e57d
diff --git a/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java b/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java
index 2ca0d96..317fd03 100644
--- a/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java
+++ b/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java
@@ -48,6 +48,8 @@
 
     private WidgetsRecyclerView mCurrentRecyclerView;
 
+    private OnContentChangeListener mOnContentChangeListener = () -> applyVerticalTransition();
+
     /**
      * The vertical distance, in pixels, until the search is pinned at the top of the screen when
      * the user scrolls down the recycler view.
@@ -82,19 +84,21 @@
         mViewHolder.mContainer.setSearchAndRecommendationScrollController(this);
         mSearchAndRecommendationViewParent = (View) mViewHolder.mContainer.getParent();
         mPrimaryRecyclerView = primaryRecyclerView;
-        mCurrentRecyclerView = mPrimaryRecyclerView;
         mWorkRecyclerView = workRecyclerView;
         mSearchRecyclerView = searchRecyclerView;
         mPrimaryWorkTabsView = personalWorkTabsView;
         mPrimaryWorkViewPager = primaryWorkViewPager;
-        mCurrentRecyclerView = mPrimaryRecyclerView;
         mTabsHeight = tabsHeight;
+        setCurrentRecyclerView(mPrimaryRecyclerView);
     }
 
     /** Sets the current active {@link WidgetsRecyclerView}. */
     public void setCurrentRecyclerView(WidgetsRecyclerView currentRecyclerView) {
+        if (mCurrentRecyclerView != null) {
+            mCurrentRecyclerView.setOnContentChangeListener(null);
+        }
         mCurrentRecyclerView = currentRecyclerView;
-        mCurrentRecyclerView = currentRecyclerView;
+        mCurrentRecyclerView.setOnContentChangeListener(mOnContentChangeListener);
         mViewHolder.mHeaderTitle.setTranslationY(0);
         mViewHolder.mRecommendedWidgetsTable.setTranslationY(0);
         mViewHolder.mSearchBar.setTranslationY(0);
@@ -216,12 +220,16 @@
         return hasMarginOrPaddingUpdated;
     }
 
-    /**
-     * Changes the displacement of collapsible views (e.g. title & widget recommendations) and fixed
-     * views (e.g. recycler views, tabs) upon scrolling.
-     */
     @Override
     public void onScrollChanged() {
+        applyVerticalTransition();
+    }
+
+    /**
+     * Changes the displacement of collapsible views (e.g. title & widget recommendations) and fixed
+     * views (e.g. recycler views, tabs) upon scrolling / content changes in the recycler view.
+     */
+    private void applyVerticalTransition() {
         // Always use the recycler view offset because fast scroller offset has a different scale.
         int recyclerViewYOffset = mCurrentRecyclerView.getCurrentScrollY();
         if (recyclerViewYOffset < 0) return;
@@ -299,4 +307,13 @@
         return view.getMeasuredHeight() + marginLayoutParams.bottomMargin
                 + marginLayoutParams.topMargin;
     }
+
+    /**
+     * A listener to be notified when there is a content change in the recycler view that may affect
+     * the relative position of the search and recommendation container.
+     */
+    public interface OnContentChangeListener {
+        /** Notifies a content change in the recycler view. */
+        void onContentChanged();
+    }
 }
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
index eb821d4..e981906 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
@@ -23,6 +23,8 @@
 import android.view.View;
 import android.widget.TableLayout;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
@@ -35,6 +37,7 @@
 import com.android.launcher3.widget.model.WidgetsListContentEntry;
 import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
 import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
+import com.android.launcher3.widget.picker.SearchAndRecommendationsScrollController.OnContentChangeListener;
 
 /**
  * The widgets recycler view.
@@ -50,6 +53,7 @@
     private boolean mTouchDownOnScroller;
     private HeaderViewDimensionsProvider mHeaderViewDimensionsProvider;
     private int mLastVisibleWidgetContentTableHeight = 0;
+    @Nullable private OnContentChangeListener mOnContentChangeListener;
 
     public WidgetsRecyclerView(Context context) {
         this(context, null);
@@ -86,6 +90,22 @@
         mAdapter = (WidgetsListAdapter) adapter;
     }
 
+    @Override
+    public void onChildAttachedToWindow(@NonNull View child) {
+        super.onChildAttachedToWindow(child);
+        if (mOnContentChangeListener != null) {
+            mOnContentChangeListener.onContentChanged();
+        }
+    }
+
+    @Override
+    public void onChildDetachedFromWindow(@NonNull View child) {
+        super.onChildDetachedFromWindow(child);
+        if (mOnContentChangeListener != null) {
+            mOnContentChangeListener.onContentChanged();
+        }
+    }
+
     /**
      * Maps the touch (from 0..1) to the adapter position that should be visible.
      */
@@ -207,6 +227,25 @@
         mHeaderViewDimensionsProvider = headerViewDimensionsProvider;
     }
 
+    @Override
+    public void scrollToTop() {
+        if (mScrollbar != null) {
+            mScrollbar.reattachThumbToScroll();
+        }
+
+        if (getLayoutManager() instanceof LinearLayoutManager) {
+            if (getCurrentScrollY() == 0) {
+                // We are at the top, so don't scrollToPosition (would cause unnecessary relayout).
+                return;
+            }
+        }
+        scrollToPosition(0);
+    }
+
+    public void setOnContentChangeListener(@Nullable OnContentChangeListener listener) {
+        mOnContentChangeListener = listener;
+    }
+
     /**
      * Returns the sum of the height, in pixels, of this list adapter's items from index 0 until
      * {@code untilIndex}.
@@ -244,19 +283,4 @@
          */
         int getHeaderViewHeight();
     }
-
-    @Override
-    public void scrollToTop() {
-        if (mScrollbar != null) {
-            mScrollbar.reattachThumbToScroll();
-        }
-
-        if (getLayoutManager() instanceof LinearLayoutManager) {
-            if (getCurrentScrollY() == 0) {
-                // We are at the top, so don't scrollToPosition (would cause unnecessary relayout).
-                return;
-            }
-        }
-        scrollToPosition(0);
-    }
 }