Loading src/com/android/launcher3/FastScrollRecyclerView.java +2 −54 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.launcher3.compat.AccessibilityManagerCompat; Loading Loading @@ -92,8 +91,7 @@ public abstract class FastScrollRecyclerView extends RecyclerView { protected int getAvailableScrollHeight() { // AvailableScrollHeight = Total height of the all items - first page height int firstPageHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); int totalHeightOfAllItems = getItemsHeight(/* untilIndex= */ getAdapter().getItemCount()); int availableScrollHeight = totalHeightOfAllItems - firstPageHeight; int availableScrollHeight = computeVerticalScrollRange() - firstPageHeight; return Math.max(0, availableScrollHeight); } Loading Loading @@ -146,10 +144,7 @@ public abstract class FastScrollRecyclerView extends RecyclerView { // IF scroller is at the very top OR there is no scroll bar because there is probably not // enough items to scroll, THEN it's okay for the container to be pulled down. if (getCurrentScrollY() == 0) { return true; } return getAdapter() == null || getAdapter().getItemCount() == 0; return computeVerticalScrollOffset() == 0; } /** Loading @@ -159,53 +154,6 @@ public abstract class FastScrollRecyclerView extends RecyclerView { return true; } /** * @return the scroll top of this recycler view. */ public int getCurrentScrollY() { Adapter adapter = getAdapter(); if (adapter == null) { return -1; } if (adapter.getItemCount() == 0 || getChildCount() == 0) { return -1; } int itemPosition = NO_POSITION; View child = null; LayoutManager layoutManager = getLayoutManager(); if (layoutManager instanceof LinearLayoutManager) { // Use the LayoutManager as the source of truth for visible positions. During // animations, the view group child may not correspond to the visible views that appear // at the top. itemPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition(); child = layoutManager.findViewByPosition(itemPosition); } if (child == null) { // If the layout manager returns null for any reason, which can happen before layout // has occurred for the position, then look at the child of this view as a ViewGroup. child = getChildAt(0); itemPosition = getChildAdapterPosition(child); } if (itemPosition == NO_POSITION) { return -1; } return getPaddingTop() + getItemsHeight(itemPosition) - layoutManager.getDecoratedTop(child); } /** * Returns the sum of the height, in pixels, of this list adapter's items from index * 0 (inclusive) until {@code untilIndex} (exclusive). If untilIndex is same as the itemCount, * it returns the full height of all the items. * * <p>If the untilIndex is larger than the total number of items in this adapter, returns the * sum of all items' height. */ protected abstract int getItemsHeight(int untilIndex); /** * Maps the touch (from 0..1) to the adapter position that should be visible. * <p>Override in each subclass of this base class. Loading src/com/android/launcher3/Launcher.java +1 −1 Original line number Diff line number Diff line Loading @@ -2794,7 +2794,7 @@ public class Launcher extends StatefulActivity<LauncherState> View v = getFirstMatch(Collections.singletonList(activeRecyclerView), preferredItem, packageAndUserAndApp); if (v != null && activeRecyclerView.getCurrentScrollY() > 0) { if (v != null && activeRecyclerView.computeVerticalScrollOffset() > 0) { RectF locationBounds = new RectF(); FloatingIconView.getLocationBoundsForView(this, v, false, locationBounds, new Rect()); Loading src/com/android/launcher3/allapps/AllAppsGridAdapter.java +13 −2 Original line number Diff line number Diff line Loading @@ -26,7 +26,9 @@ import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.core.view.accessibility.AccessibilityRecordCompat; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView.Adapter; import com.android.launcher3.util.ScrollableLayoutManager; import com.android.launcher3.views.ActivityContext; import java.util.List; Loading Loading @@ -62,10 +64,10 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends /** * A subclass of GridLayoutManager that overrides accessibility values during app search. */ public class AppsGridLayoutManager extends GridLayoutManager { public class AppsGridLayoutManager extends ScrollableLayoutManager { public AppsGridLayoutManager(Context context) { super(context, 1, GridLayoutManager.VERTICAL, false); super(context); } @Override Loading Loading @@ -125,6 +127,15 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends } return extraRows; } @Override protected int incrementTotalHeight(Adapter adapter, int position, int heightUntilLastPos) { AllAppsGridAdapter.AdapterItem item = mApps.getAdapterItems().get(position); // only account for the first icon in the row since they are the same size within a row return (isIconViewType(item.viewType) && item.rowAppIndex != 0) ? heightUntilLastPos : (heightUntilLastPos + mCachedSizes.get(item.viewType)); } } @Override Loading src/com/android/launcher3/allapps/AllAppsRecyclerView.java +3 −96 Original line number Diff line number Diff line Loading @@ -15,8 +15,6 @@ */ package com.android.launcher3.allapps; import static android.view.View.MeasureSpec.UNSPECIFIED; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_SCROLLED; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_VERTICAL_SWIPE_END; Loading @@ -26,7 +24,6 @@ import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.util.Log; import android.util.SparseIntArray; import androidx.recyclerview.widget.RecyclerView; Loading @@ -49,40 +46,10 @@ public class AllAppsRecyclerView extends FastScrollRecyclerView { private static final boolean DEBUG = false; private static final boolean DEBUG_LATENCY = Utilities.isPropertyEnabled(SEARCH_LOGGING); protected AlphabeticalAppsList<?> mApps; protected final int mNumAppsPerRow; // The specific view heights that we use to calculate scroll private final SparseIntArray mViewHeights = new SparseIntArray(); private final SparseIntArray mCachedScrollPositions = new SparseIntArray(); private final AllAppsFastScrollHelper mFastScrollHelper; private final AdapterDataObserver mObserver = new RecyclerView.AdapterDataObserver() { public void onChanged() { mCachedScrollPositions.clear(); } @Override public void onItemRangeChanged(int positionStart, int itemCount) { onChanged(); } @Override public void onItemRangeInserted(int positionStart, int itemCount) { onChanged(); } @Override public void onItemRangeRemoved(int positionStart, int itemCount) { onChanged(); } @Override public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { onChanged(); } }; protected AlphabeticalAppsList<?> mApps; public AllAppsRecyclerView(Context context) { this(context, null); Loading Loading @@ -122,12 +89,8 @@ public class AllAppsRecyclerView extends FastScrollRecyclerView { pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_ALL_APPS_DIVIDER, 1); pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_ICON, approxRows * (mNumAppsPerRow + 1)); mViewHeights.clear(); mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_ICON, grid.allAppsCellHeightPx); } @Override public void onDraw(Canvas c) { if (DEBUG) { Loading Loading @@ -199,17 +162,6 @@ public class AllAppsRecyclerView extends FastScrollRecyclerView { mFastScrollHelper.onFastScrollCompleted(); } @Override public void setAdapter(Adapter adapter) { if (getAdapter() != null) { getAdapter().unregisterAdapterDataObserver(mObserver); } super.setAdapter(adapter); if (adapter != null) { adapter.registerAdapterDataObserver(mObserver); } } @Override protected boolean isPaddingOffsetRequired() { return true; Loading @@ -231,13 +183,13 @@ public class AllAppsRecyclerView extends FastScrollRecyclerView { List<AllAppsGridAdapter.AdapterItem> items = mApps.getAdapterItems(); // Skip early if there are no items or we haven't been measured if (items.isEmpty() || mNumAppsPerRow == 0) { if (items.isEmpty() || mNumAppsPerRow == 0 || getChildCount() == 0) { mScrollbar.setThumbOffsetY(-1); return; } // Skip early if, there no child laid out in the container. int scrollY = getCurrentScrollY(); int scrollY = computeVerticalScrollOffset(); if (scrollY < 0) { mScrollbar.setThumbOffsetY(-1); return; Loading Loading @@ -292,51 +244,6 @@ public class AllAppsRecyclerView extends FastScrollRecyclerView { } } @Override protected int getItemsHeight(int position) { List<AllAppsGridAdapter.AdapterItem> items = mApps.getAdapterItems(); AllAppsGridAdapter.AdapterItem posItem = position < items.size() ? items.get(position) : null; int y = mCachedScrollPositions.get(position, -1); if (y < 0) { y = 0; for (int i = 0; i < position; i++) { AllAppsGridAdapter.AdapterItem item = items.get(i); if (AllAppsGridAdapter.isIconViewType(item.viewType)) { // Break once we reach the desired row if (posItem != null && posItem.viewType == item.viewType && posItem.rowIndex == item.rowIndex) { break; } // Otherwise, only account for the first icon in the row since they are the same // size within a row if (item.rowAppIndex == 0) { y += mViewHeights.get(item.viewType, 0); } } else { // Rest of the views span the full width int elHeight = mViewHeights.get(item.viewType); if (elHeight == 0) { ViewHolder holder = findViewHolderForAdapterPosition(i); if (holder == null) { holder = getAdapter().createViewHolder(this, item.viewType); getAdapter().onBindViewHolder(holder, i); holder.itemView.measure(UNSPECIFIED, UNSPECIFIED); elHeight = holder.itemView.getMeasuredHeight(); getRecycledViewPool().putRecycledView(holder); } else { elHeight = holder.itemView.getMeasuredHeight(); } } y += elHeight; } } mCachedScrollPositions.put(position, y); } return y; } public int getScrollBarTop() { return getResources().getDimensionPixelOffset(R.dimen.all_apps_header_top_padding); } Loading src/com/android/launcher3/allapps/BaseAllAppsContainerView.java +2 −1 Original line number Diff line number Diff line Loading @@ -103,7 +103,8 @@ public abstract class BaseAllAppsContainerView<T extends Context & ActivityConte new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { updateHeaderScroll(((AllAppsRecyclerView) recyclerView).getCurrentScrollY()); updateHeaderScroll( ((AllAppsRecyclerView) recyclerView).computeVerticalScrollOffset()); } }; Loading Loading
src/com/android/launcher3/FastScrollRecyclerView.java +2 −54 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.launcher3.compat.AccessibilityManagerCompat; Loading Loading @@ -92,8 +91,7 @@ public abstract class FastScrollRecyclerView extends RecyclerView { protected int getAvailableScrollHeight() { // AvailableScrollHeight = Total height of the all items - first page height int firstPageHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); int totalHeightOfAllItems = getItemsHeight(/* untilIndex= */ getAdapter().getItemCount()); int availableScrollHeight = totalHeightOfAllItems - firstPageHeight; int availableScrollHeight = computeVerticalScrollRange() - firstPageHeight; return Math.max(0, availableScrollHeight); } Loading Loading @@ -146,10 +144,7 @@ public abstract class FastScrollRecyclerView extends RecyclerView { // IF scroller is at the very top OR there is no scroll bar because there is probably not // enough items to scroll, THEN it's okay for the container to be pulled down. if (getCurrentScrollY() == 0) { return true; } return getAdapter() == null || getAdapter().getItemCount() == 0; return computeVerticalScrollOffset() == 0; } /** Loading @@ -159,53 +154,6 @@ public abstract class FastScrollRecyclerView extends RecyclerView { return true; } /** * @return the scroll top of this recycler view. */ public int getCurrentScrollY() { Adapter adapter = getAdapter(); if (adapter == null) { return -1; } if (adapter.getItemCount() == 0 || getChildCount() == 0) { return -1; } int itemPosition = NO_POSITION; View child = null; LayoutManager layoutManager = getLayoutManager(); if (layoutManager instanceof LinearLayoutManager) { // Use the LayoutManager as the source of truth for visible positions. During // animations, the view group child may not correspond to the visible views that appear // at the top. itemPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition(); child = layoutManager.findViewByPosition(itemPosition); } if (child == null) { // If the layout manager returns null for any reason, which can happen before layout // has occurred for the position, then look at the child of this view as a ViewGroup. child = getChildAt(0); itemPosition = getChildAdapterPosition(child); } if (itemPosition == NO_POSITION) { return -1; } return getPaddingTop() + getItemsHeight(itemPosition) - layoutManager.getDecoratedTop(child); } /** * Returns the sum of the height, in pixels, of this list adapter's items from index * 0 (inclusive) until {@code untilIndex} (exclusive). If untilIndex is same as the itemCount, * it returns the full height of all the items. * * <p>If the untilIndex is larger than the total number of items in this adapter, returns the * sum of all items' height. */ protected abstract int getItemsHeight(int untilIndex); /** * Maps the touch (from 0..1) to the adapter position that should be visible. * <p>Override in each subclass of this base class. Loading
src/com/android/launcher3/Launcher.java +1 −1 Original line number Diff line number Diff line Loading @@ -2794,7 +2794,7 @@ public class Launcher extends StatefulActivity<LauncherState> View v = getFirstMatch(Collections.singletonList(activeRecyclerView), preferredItem, packageAndUserAndApp); if (v != null && activeRecyclerView.getCurrentScrollY() > 0) { if (v != null && activeRecyclerView.computeVerticalScrollOffset() > 0) { RectF locationBounds = new RectF(); FloatingIconView.getLocationBoundsForView(this, v, false, locationBounds, new Rect()); Loading
src/com/android/launcher3/allapps/AllAppsGridAdapter.java +13 −2 Original line number Diff line number Diff line Loading @@ -26,7 +26,9 @@ import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.core.view.accessibility.AccessibilityRecordCompat; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView.Adapter; import com.android.launcher3.util.ScrollableLayoutManager; import com.android.launcher3.views.ActivityContext; import java.util.List; Loading Loading @@ -62,10 +64,10 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends /** * A subclass of GridLayoutManager that overrides accessibility values during app search. */ public class AppsGridLayoutManager extends GridLayoutManager { public class AppsGridLayoutManager extends ScrollableLayoutManager { public AppsGridLayoutManager(Context context) { super(context, 1, GridLayoutManager.VERTICAL, false); super(context); } @Override Loading Loading @@ -125,6 +127,15 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends } return extraRows; } @Override protected int incrementTotalHeight(Adapter adapter, int position, int heightUntilLastPos) { AllAppsGridAdapter.AdapterItem item = mApps.getAdapterItems().get(position); // only account for the first icon in the row since they are the same size within a row return (isIconViewType(item.viewType) && item.rowAppIndex != 0) ? heightUntilLastPos : (heightUntilLastPos + mCachedSizes.get(item.viewType)); } } @Override Loading
src/com/android/launcher3/allapps/AllAppsRecyclerView.java +3 −96 Original line number Diff line number Diff line Loading @@ -15,8 +15,6 @@ */ package com.android.launcher3.allapps; import static android.view.View.MeasureSpec.UNSPECIFIED; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_SCROLLED; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_VERTICAL_SWIPE_END; Loading @@ -26,7 +24,6 @@ import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.util.Log; import android.util.SparseIntArray; import androidx.recyclerview.widget.RecyclerView; Loading @@ -49,40 +46,10 @@ public class AllAppsRecyclerView extends FastScrollRecyclerView { private static final boolean DEBUG = false; private static final boolean DEBUG_LATENCY = Utilities.isPropertyEnabled(SEARCH_LOGGING); protected AlphabeticalAppsList<?> mApps; protected final int mNumAppsPerRow; // The specific view heights that we use to calculate scroll private final SparseIntArray mViewHeights = new SparseIntArray(); private final SparseIntArray mCachedScrollPositions = new SparseIntArray(); private final AllAppsFastScrollHelper mFastScrollHelper; private final AdapterDataObserver mObserver = new RecyclerView.AdapterDataObserver() { public void onChanged() { mCachedScrollPositions.clear(); } @Override public void onItemRangeChanged(int positionStart, int itemCount) { onChanged(); } @Override public void onItemRangeInserted(int positionStart, int itemCount) { onChanged(); } @Override public void onItemRangeRemoved(int positionStart, int itemCount) { onChanged(); } @Override public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { onChanged(); } }; protected AlphabeticalAppsList<?> mApps; public AllAppsRecyclerView(Context context) { this(context, null); Loading Loading @@ -122,12 +89,8 @@ public class AllAppsRecyclerView extends FastScrollRecyclerView { pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_ALL_APPS_DIVIDER, 1); pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_ICON, approxRows * (mNumAppsPerRow + 1)); mViewHeights.clear(); mViewHeights.put(AllAppsGridAdapter.VIEW_TYPE_ICON, grid.allAppsCellHeightPx); } @Override public void onDraw(Canvas c) { if (DEBUG) { Loading Loading @@ -199,17 +162,6 @@ public class AllAppsRecyclerView extends FastScrollRecyclerView { mFastScrollHelper.onFastScrollCompleted(); } @Override public void setAdapter(Adapter adapter) { if (getAdapter() != null) { getAdapter().unregisterAdapterDataObserver(mObserver); } super.setAdapter(adapter); if (adapter != null) { adapter.registerAdapterDataObserver(mObserver); } } @Override protected boolean isPaddingOffsetRequired() { return true; Loading @@ -231,13 +183,13 @@ public class AllAppsRecyclerView extends FastScrollRecyclerView { List<AllAppsGridAdapter.AdapterItem> items = mApps.getAdapterItems(); // Skip early if there are no items or we haven't been measured if (items.isEmpty() || mNumAppsPerRow == 0) { if (items.isEmpty() || mNumAppsPerRow == 0 || getChildCount() == 0) { mScrollbar.setThumbOffsetY(-1); return; } // Skip early if, there no child laid out in the container. int scrollY = getCurrentScrollY(); int scrollY = computeVerticalScrollOffset(); if (scrollY < 0) { mScrollbar.setThumbOffsetY(-1); return; Loading Loading @@ -292,51 +244,6 @@ public class AllAppsRecyclerView extends FastScrollRecyclerView { } } @Override protected int getItemsHeight(int position) { List<AllAppsGridAdapter.AdapterItem> items = mApps.getAdapterItems(); AllAppsGridAdapter.AdapterItem posItem = position < items.size() ? items.get(position) : null; int y = mCachedScrollPositions.get(position, -1); if (y < 0) { y = 0; for (int i = 0; i < position; i++) { AllAppsGridAdapter.AdapterItem item = items.get(i); if (AllAppsGridAdapter.isIconViewType(item.viewType)) { // Break once we reach the desired row if (posItem != null && posItem.viewType == item.viewType && posItem.rowIndex == item.rowIndex) { break; } // Otherwise, only account for the first icon in the row since they are the same // size within a row if (item.rowAppIndex == 0) { y += mViewHeights.get(item.viewType, 0); } } else { // Rest of the views span the full width int elHeight = mViewHeights.get(item.viewType); if (elHeight == 0) { ViewHolder holder = findViewHolderForAdapterPosition(i); if (holder == null) { holder = getAdapter().createViewHolder(this, item.viewType); getAdapter().onBindViewHolder(holder, i); holder.itemView.measure(UNSPECIFIED, UNSPECIFIED); elHeight = holder.itemView.getMeasuredHeight(); getRecycledViewPool().putRecycledView(holder); } else { elHeight = holder.itemView.getMeasuredHeight(); } } y += elHeight; } } mCachedScrollPositions.put(position, y); } return y; } public int getScrollBarTop() { return getResources().getDimensionPixelOffset(R.dimen.all_apps_header_top_padding); } Loading
src/com/android/launcher3/allapps/BaseAllAppsContainerView.java +2 −1 Original line number Diff line number Diff line Loading @@ -103,7 +103,8 @@ public abstract class BaseAllAppsContainerView<T extends Context & ActivityConte new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { updateHeaderScroll(((AllAppsRecyclerView) recyclerView).getCurrentScrollY()); updateHeaderScroll( ((AllAppsRecyclerView) recyclerView).computeVerticalScrollOffset()); } }; Loading