diff --git a/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java b/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java index 2ca0d96eec..317fd03afe 100644 --- a/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java +++ b/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java @@ -48,6 +48,8 @@ final class SearchAndRecommendationsScrollController implements 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 @@ final class SearchAndRecommendationsScrollController implements 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 @@ final class SearchAndRecommendationsScrollController implements 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 @@ final class SearchAndRecommendationsScrollController implements 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 eb821d4eab..e981906774 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.MotionEvent; 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.WidgetsListBaseEntry; 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 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch 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 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch 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 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch 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 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch */ 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); - } }