Align 'No widgets available' text box properly in Widget picker.

Bug: 186209657
Test: Tested manually
Change-Id: I85fa43cd745a8c9f9601d25ed3a35f512506234d
diff --git a/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java b/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java
index 6781824..6643779 100644
--- a/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java
+++ b/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java
@@ -21,6 +21,7 @@
 import android.view.View;
 import android.view.ViewGroup.MarginLayoutParams;
 import android.widget.RelativeLayout;
+import android.widget.TextView;
 
 import androidx.annotation.Nullable;
 
@@ -39,9 +40,11 @@
     private final View mSearchAndRecommendationViewParent;
     private final WidgetsRecyclerView mPrimaryRecyclerView;
     private final WidgetsRecyclerView mSearchRecyclerView;
+    private final TextView mNoWidgetsView;
     private final int mTabsHeight;
     private final ValueAnimator mAnimator = ValueAnimator.ofInt(0, 0);
     private final Point mTempOffset = new Point();
+    private int mBottomInset;
 
     // The following are only non null if mHasWorkProfile is true.
     @Nullable private final WidgetsRecyclerView mWorkRecyclerView;
@@ -81,7 +84,8 @@
             @Nullable WidgetsRecyclerView workRecyclerView,
             WidgetsRecyclerView searchRecyclerView,
             @Nullable View personalWorkTabsView,
-            @Nullable PersonalWorkPagedView primaryWorkViewPager) {
+            @Nullable PersonalWorkPagedView primaryWorkViewPager,
+            TextView noWidgetsView) {
         mHasWorkProfile = hasWorkProfile;
         mViewHolder = viewHolder;
         mViewHolder.mContainer.setSearchAndRecommendationScrollController(this);
@@ -92,6 +96,7 @@
         mPrimaryWorkTabsView = personalWorkTabsView;
         mPrimaryWorkViewPager = primaryWorkViewPager;
         mTabsHeight = tabsHeight;
+        mNoWidgetsView = noWidgetsView;
         setCurrentRecyclerView(mPrimaryRecyclerView, /* animateReset= */ false);
     }
 
@@ -114,6 +119,15 @@
     }
 
     /**
+     * Updates padding of {@link WidgetsFullSheet} contents to include {@code bottomInset} wherever
+     * necessary.
+     */
+    public boolean updateBottomInset(int bottomInset) {
+        mBottomInset = bottomInset;
+        return updateMarginAndPadding();
+    }
+
+    /**
      * Updates the margin and padding of {@link WidgetsFullSheet} to accumulate collapsible views.
      *
      * @return {@code true} if margins or/and padding of views in the search and recommendations
@@ -129,6 +143,8 @@
                         + measureHeightWithVerticalMargins(mViewHolder.mRecommendedWidgetsTable);
 
         int topContainerHeight = measureHeightWithVerticalMargins(mViewHolder.mContainer);
+        int noWidgetsViewHeight =  topContainerHeight - mBottomInset;
+
         if (mHasWorkProfile) {
             mCollapsibleHeightForTabs = measureHeightWithVerticalMargins(mViewHolder.mHeaderTitle)
                     + measureHeightWithVerticalMargins(mViewHolder.mRecommendedWidgetsTable);
@@ -180,6 +196,10 @@
             int topOffsetAfterAllViewsCollapsed =
                     topContainerHeight + mTabsHeight - mCollapsibleHeightForTabs;
 
+            if (mPrimaryWorkTabsView.getVisibility() == View.VISIBLE) {
+                noWidgetsViewHeight += mTabsHeight;
+            }
+
             RelativeLayout.LayoutParams viewPagerLayoutParams =
                     (RelativeLayout.LayoutParams) mPrimaryWorkViewPager.getLayoutParams();
             if (viewPagerLayoutParams.topMargin != topOffsetAfterAllViewsCollapsed) {
@@ -222,6 +242,14 @@
                     mSearchRecyclerView.getPaddingBottom());
             hasMarginOrPaddingUpdated = true;
         }
+        if (mNoWidgetsView.getPaddingTop() != noWidgetsViewHeight) {
+            mNoWidgetsView.setPadding(
+                    mNoWidgetsView.getPaddingLeft(),
+                    noWidgetsViewHeight,
+                    mNoWidgetsView.getPaddingRight(),
+                    mNoWidgetsView.getPaddingBottom());
+            hasMarginOrPaddingUpdated = true;
+        }
         return hasMarginOrPaddingUpdated;
     }
 
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 42ff249..039cad8 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -92,8 +92,8 @@
     private final boolean mHasWorkProfile;
     private final SparseArray<AdapterHolder> mAdapters = new SparseArray();
     private final UserHandle mCurrentUser = Process.myUserHandle();
-    private final Predicate<WidgetsListBaseEntry> mPrimaryWidgetsFilter = entry ->
-            mCurrentUser.equals(entry.mPkgItem.user);
+    private final Predicate<WidgetsListBaseEntry> mPrimaryWidgetsFilter =
+            entry -> mCurrentUser.equals(entry.mPkgItem.user);
     private final Predicate<WidgetsListBaseEntry> mWorkWidgetsFilter =
             mPrimaryWidgetsFilter.negate();
     private final OnLayoutChangeListener mLayoutChangeListenerToShowTips =
@@ -131,6 +131,7 @@
     @Nullable private WidgetsRecyclerView mCurrentWidgetsRecyclerView;
     @Nullable private PersonalWorkPagedView mViewPager;
     private boolean mIsInSearchMode;
+    private boolean mIsNoWidgetsViewNeeded;
     private int mMaxSpansPerRow = 4;
     private View mTabsView;
     private TextView mNoWidgetsView;
@@ -187,6 +188,7 @@
 
         layoutInflater.inflate(R.layout.widgets_full_sheet_search_and_recommendations, springLayout,
                 true);
+        mNoWidgetsView = findViewById(R.id.no_widgets_text);
         mSearchAndRecommendationViewHolder = new SearchAndRecommendationViewHolder(
                 findViewById(R.id.search_and_recommendations_container));
         mSearchAndRecommendationsScrollController = new SearchAndRecommendationsScrollController(
@@ -197,10 +199,10 @@
                 mHasWorkProfile ? findViewById(R.id.work_widgets_list_view) : null,
                 findViewById(R.id.search_widgets_list_view),
                 mTabsView,
-                mViewPager);
+                mViewPager,
+                mNoWidgetsView);
         fastScroller.setOnFastScrollChangeListener(mSearchAndRecommendationsScrollController);
 
-        mNoWidgetsView = findViewById(R.id.no_widgets_text);
 
         onRecommendedWidgetsBound();
         onWidgetsBound();
@@ -295,6 +297,7 @@
         if (mHasWorkProfile) {
             setBottomPadding(mAdapters.get(AdapterHolder.WORK).mWidgetsRecyclerView, insets.bottom);
         }
+        mSearchAndRecommendationsScrollController.updateBottomInset(insets.bottom);
         if (insets.bottom > 0) {
             setupNavBarColor();
         } else {
@@ -410,6 +413,16 @@
         } else {
             updateRecyclerViewVisibility(primaryUserAdapterHolder);
         }
+        // Update recommended widgets section so that it occupies appropriate space on screen to
+        // leave enough space for presence/absence of mNoWidgetsView.
+        boolean isNoWidgetsViewNeeded =
+                mAdapters.get(AdapterHolder.PRIMARY).mWidgetsListAdapter.getItemCount() == 0
+                        || (mHasWorkProfile && mAdapters.get(AdapterHolder.WORK)
+                                .mWidgetsListAdapter.getItemCount() == 0);
+        if (mIsNoWidgetsViewNeeded != isNoWidgetsViewNeeded) {
+            mIsNoWidgetsViewNeeded = isNoWidgetsViewNeeded;
+            onRecommendedWidgetsBound();
+        }
     }
 
     @Override
@@ -476,9 +489,19 @@
         WidgetsRecommendationTableLayout table =
                 mSearchAndRecommendationViewHolder.mRecommendedWidgetsTable;
         if (recommendedWidgets.size() > 0) {
-            float maxTableHeight =
-                    (mActivityContext.getDeviceProfile().availableHeightPx - mTabsHeight
-                            - getHeaderViewHeight()) * RECOMMENDATION_TABLE_HEIGHT_RATIO;
+            float noWidgetsViewHeight = 0;
+            if (mIsNoWidgetsViewNeeded) {
+                // Make sure recommended section leaves enough space for noWidgetsView.
+                Rect noWidgetsViewTextBounds = new Rect();
+                mNoWidgetsView.getPaint()
+                        .getTextBounds(mNoWidgetsView.getText().toString(), /* start= */ 0,
+                                mNoWidgetsView.getText().length(), noWidgetsViewTextBounds);
+                noWidgetsViewHeight = noWidgetsViewTextBounds.height();
+            }
+            float maxTableHeight = (mActivityContext.getDeviceProfile().availableHeightPx
+                                        - mTabsHeight - getHeaderViewHeight() - noWidgetsViewHeight)
+                                                * RECOMMENDATION_TABLE_HEIGHT_RATIO;
+
             List<ArrayList<WidgetItem>> recommendedWidgetsInTable =
                     WidgetsTableUtils.groupWidgetItemsIntoTable(recommendedWidgets,
                             mMaxSpansPerRow);