Loading src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java +23 −6 Original line number Original line Diff line number Diff line Loading @@ -48,6 +48,8 @@ final class SearchAndRecommendationsScrollController implements private WidgetsRecyclerView mCurrentRecyclerView; 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 vertical distance, in pixels, until the search is pinned at the top of the screen when * the user scrolls down the recycler view. * the user scrolls down the recycler view. Loading Loading @@ -82,19 +84,21 @@ final class SearchAndRecommendationsScrollController implements mViewHolder.mContainer.setSearchAndRecommendationScrollController(this); mViewHolder.mContainer.setSearchAndRecommendationScrollController(this); mSearchAndRecommendationViewParent = (View) mViewHolder.mContainer.getParent(); mSearchAndRecommendationViewParent = (View) mViewHolder.mContainer.getParent(); mPrimaryRecyclerView = primaryRecyclerView; mPrimaryRecyclerView = primaryRecyclerView; mCurrentRecyclerView = mPrimaryRecyclerView; mWorkRecyclerView = workRecyclerView; mWorkRecyclerView = workRecyclerView; mSearchRecyclerView = searchRecyclerView; mSearchRecyclerView = searchRecyclerView; mPrimaryWorkTabsView = personalWorkTabsView; mPrimaryWorkTabsView = personalWorkTabsView; mPrimaryWorkViewPager = primaryWorkViewPager; mPrimaryWorkViewPager = primaryWorkViewPager; mCurrentRecyclerView = mPrimaryRecyclerView; mTabsHeight = tabsHeight; mTabsHeight = tabsHeight; setCurrentRecyclerView(mPrimaryRecyclerView); } } /** Sets the current active {@link WidgetsRecyclerView}. */ /** Sets the current active {@link WidgetsRecyclerView}. */ public void setCurrentRecyclerView(WidgetsRecyclerView currentRecyclerView) { public void setCurrentRecyclerView(WidgetsRecyclerView currentRecyclerView) { if (mCurrentRecyclerView != null) { mCurrentRecyclerView.setOnContentChangeListener(null); } mCurrentRecyclerView = currentRecyclerView; mCurrentRecyclerView = currentRecyclerView; mCurrentRecyclerView = currentRecyclerView; mCurrentRecyclerView.setOnContentChangeListener(mOnContentChangeListener); mViewHolder.mHeaderTitle.setTranslationY(0); mViewHolder.mHeaderTitle.setTranslationY(0); mViewHolder.mRecommendedWidgetsTable.setTranslationY(0); mViewHolder.mRecommendedWidgetsTable.setTranslationY(0); mViewHolder.mSearchBar.setTranslationY(0); mViewHolder.mSearchBar.setTranslationY(0); Loading Loading @@ -216,12 +220,16 @@ final class SearchAndRecommendationsScrollController implements return hasMarginOrPaddingUpdated; return hasMarginOrPaddingUpdated; } } @Override public void onScrollChanged() { applyVerticalTransition(); } /** /** * Changes the displacement of collapsible views (e.g. title & widget recommendations) and fixed * Changes the displacement of collapsible views (e.g. title & widget recommendations) and fixed * views (e.g. recycler views, tabs) upon scrolling. * views (e.g. recycler views, tabs) upon scrolling / content changes in the recycler view. */ */ @Override private void applyVerticalTransition() { public void onScrollChanged() { // Always use the recycler view offset because fast scroller offset has a different scale. // Always use the recycler view offset because fast scroller offset has a different scale. int recyclerViewYOffset = mCurrentRecyclerView.getCurrentScrollY(); int recyclerViewYOffset = mCurrentRecyclerView.getCurrentScrollY(); if (recyclerViewYOffset < 0) return; if (recyclerViewYOffset < 0) return; Loading Loading @@ -299,4 +307,13 @@ final class SearchAndRecommendationsScrollController implements return view.getMeasuredHeight() + marginLayoutParams.bottomMargin return view.getMeasuredHeight() + marginLayoutParams.bottomMargin + marginLayoutParams.topMargin; + 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(); } } } src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java +39 −15 Original line number Original line Diff line number Diff line Loading @@ -23,6 +23,8 @@ import android.view.MotionEvent; import android.view.View; import android.view.View; import android.widget.TableLayout; import android.widget.TableLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener; import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener; Loading @@ -35,6 +37,7 @@ import com.android.launcher3.widget.model.WidgetsListBaseEntry; import com.android.launcher3.widget.model.WidgetsListContentEntry; import com.android.launcher3.widget.model.WidgetsListContentEntry; import com.android.launcher3.widget.model.WidgetsListHeaderEntry; import com.android.launcher3.widget.model.WidgetsListHeaderEntry; import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry; import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry; import com.android.launcher3.widget.picker.SearchAndRecommendationsScrollController.OnContentChangeListener; /** /** * The widgets recycler view. * The widgets recycler view. Loading @@ -50,6 +53,7 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch private boolean mTouchDownOnScroller; private boolean mTouchDownOnScroller; private HeaderViewDimensionsProvider mHeaderViewDimensionsProvider; private HeaderViewDimensionsProvider mHeaderViewDimensionsProvider; private int mLastVisibleWidgetContentTableHeight = 0; private int mLastVisibleWidgetContentTableHeight = 0; @Nullable private OnContentChangeListener mOnContentChangeListener; public WidgetsRecyclerView(Context context) { public WidgetsRecyclerView(Context context) { this(context, null); this(context, null); Loading Loading @@ -86,6 +90,22 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch mAdapter = (WidgetsListAdapter) adapter; 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. * Maps the touch (from 0..1) to the adapter position that should be visible. */ */ Loading Loading @@ -207,6 +227,25 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch mHeaderViewDimensionsProvider = headerViewDimensionsProvider; 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 * Returns the sum of the height, in pixels, of this list adapter's items from index 0 until * {@code untilIndex}. * {@code untilIndex}. Loading Loading @@ -244,19 +283,4 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch */ */ int getHeaderViewHeight(); 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); } } } Loading
src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java +23 −6 Original line number Original line Diff line number Diff line Loading @@ -48,6 +48,8 @@ final class SearchAndRecommendationsScrollController implements private WidgetsRecyclerView mCurrentRecyclerView; 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 vertical distance, in pixels, until the search is pinned at the top of the screen when * the user scrolls down the recycler view. * the user scrolls down the recycler view. Loading Loading @@ -82,19 +84,21 @@ final class SearchAndRecommendationsScrollController implements mViewHolder.mContainer.setSearchAndRecommendationScrollController(this); mViewHolder.mContainer.setSearchAndRecommendationScrollController(this); mSearchAndRecommendationViewParent = (View) mViewHolder.mContainer.getParent(); mSearchAndRecommendationViewParent = (View) mViewHolder.mContainer.getParent(); mPrimaryRecyclerView = primaryRecyclerView; mPrimaryRecyclerView = primaryRecyclerView; mCurrentRecyclerView = mPrimaryRecyclerView; mWorkRecyclerView = workRecyclerView; mWorkRecyclerView = workRecyclerView; mSearchRecyclerView = searchRecyclerView; mSearchRecyclerView = searchRecyclerView; mPrimaryWorkTabsView = personalWorkTabsView; mPrimaryWorkTabsView = personalWorkTabsView; mPrimaryWorkViewPager = primaryWorkViewPager; mPrimaryWorkViewPager = primaryWorkViewPager; mCurrentRecyclerView = mPrimaryRecyclerView; mTabsHeight = tabsHeight; mTabsHeight = tabsHeight; setCurrentRecyclerView(mPrimaryRecyclerView); } } /** Sets the current active {@link WidgetsRecyclerView}. */ /** Sets the current active {@link WidgetsRecyclerView}. */ public void setCurrentRecyclerView(WidgetsRecyclerView currentRecyclerView) { public void setCurrentRecyclerView(WidgetsRecyclerView currentRecyclerView) { if (mCurrentRecyclerView != null) { mCurrentRecyclerView.setOnContentChangeListener(null); } mCurrentRecyclerView = currentRecyclerView; mCurrentRecyclerView = currentRecyclerView; mCurrentRecyclerView = currentRecyclerView; mCurrentRecyclerView.setOnContentChangeListener(mOnContentChangeListener); mViewHolder.mHeaderTitle.setTranslationY(0); mViewHolder.mHeaderTitle.setTranslationY(0); mViewHolder.mRecommendedWidgetsTable.setTranslationY(0); mViewHolder.mRecommendedWidgetsTable.setTranslationY(0); mViewHolder.mSearchBar.setTranslationY(0); mViewHolder.mSearchBar.setTranslationY(0); Loading Loading @@ -216,12 +220,16 @@ final class SearchAndRecommendationsScrollController implements return hasMarginOrPaddingUpdated; return hasMarginOrPaddingUpdated; } } @Override public void onScrollChanged() { applyVerticalTransition(); } /** /** * Changes the displacement of collapsible views (e.g. title & widget recommendations) and fixed * Changes the displacement of collapsible views (e.g. title & widget recommendations) and fixed * views (e.g. recycler views, tabs) upon scrolling. * views (e.g. recycler views, tabs) upon scrolling / content changes in the recycler view. */ */ @Override private void applyVerticalTransition() { public void onScrollChanged() { // Always use the recycler view offset because fast scroller offset has a different scale. // Always use the recycler view offset because fast scroller offset has a different scale. int recyclerViewYOffset = mCurrentRecyclerView.getCurrentScrollY(); int recyclerViewYOffset = mCurrentRecyclerView.getCurrentScrollY(); if (recyclerViewYOffset < 0) return; if (recyclerViewYOffset < 0) return; Loading Loading @@ -299,4 +307,13 @@ final class SearchAndRecommendationsScrollController implements return view.getMeasuredHeight() + marginLayoutParams.bottomMargin return view.getMeasuredHeight() + marginLayoutParams.bottomMargin + marginLayoutParams.topMargin; + 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(); } } }
src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java +39 −15 Original line number Original line Diff line number Diff line Loading @@ -23,6 +23,8 @@ import android.view.MotionEvent; import android.view.View; import android.view.View; import android.widget.TableLayout; import android.widget.TableLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener; import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener; Loading @@ -35,6 +37,7 @@ import com.android.launcher3.widget.model.WidgetsListBaseEntry; import com.android.launcher3.widget.model.WidgetsListContentEntry; import com.android.launcher3.widget.model.WidgetsListContentEntry; import com.android.launcher3.widget.model.WidgetsListHeaderEntry; import com.android.launcher3.widget.model.WidgetsListHeaderEntry; import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry; import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry; import com.android.launcher3.widget.picker.SearchAndRecommendationsScrollController.OnContentChangeListener; /** /** * The widgets recycler view. * The widgets recycler view. Loading @@ -50,6 +53,7 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch private boolean mTouchDownOnScroller; private boolean mTouchDownOnScroller; private HeaderViewDimensionsProvider mHeaderViewDimensionsProvider; private HeaderViewDimensionsProvider mHeaderViewDimensionsProvider; private int mLastVisibleWidgetContentTableHeight = 0; private int mLastVisibleWidgetContentTableHeight = 0; @Nullable private OnContentChangeListener mOnContentChangeListener; public WidgetsRecyclerView(Context context) { public WidgetsRecyclerView(Context context) { this(context, null); this(context, null); Loading Loading @@ -86,6 +90,22 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch mAdapter = (WidgetsListAdapter) adapter; 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. * Maps the touch (from 0..1) to the adapter position that should be visible. */ */ Loading Loading @@ -207,6 +227,25 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch mHeaderViewDimensionsProvider = headerViewDimensionsProvider; 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 * Returns the sum of the height, in pixels, of this list adapter's items from index 0 until * {@code untilIndex}. * {@code untilIndex}. Loading Loading @@ -244,19 +283,4 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch */ */ int getHeaderViewHeight(); 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); } } }