Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cee6ddf3 authored by Hui Kang's avatar Hui Kang
Browse files

Revert "Updating the scroll calculation from recyclerView to avoid view inflation"

This reverts commit 20bbe95d.

Reason for revert: Causing flake in Ironwood test: b/248295569

Test: ABTD
Before: Flaky, 14/50 PASSED
https://android-build.googleplex.com/builds/abtd/run/L33900000956890639

Revert: 50/50 PASSED
https://android-build.googleplex.com/builds/abtd/run/L49200000956887317

Change-Id: I41f4428c74e581323f90c716a7852b5e553ae27d
parent 20bbe95d
Loading
Loading
Loading
Loading
+54 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ 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;
@@ -91,7 +92,8 @@ 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 availableScrollHeight = computeVerticalScrollRange() - firstPageHeight;
        int totalHeightOfAllItems = getItemsHeight(/* untilIndex= */ getAdapter().getItemCount());
        int availableScrollHeight = totalHeightOfAllItems - firstPageHeight;
        return Math.max(0, availableScrollHeight);
    }

@@ -144,7 +146,10 @@ 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.
        return computeVerticalScrollOffset() == 0;
        if (getCurrentScrollY() == 0) {
            return true;
        }
        return getAdapter() == null || getAdapter().getItemCount() == 0;
    }

    /**
@@ -154,6 +159,53 @@ 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.
+1 −1
Original line number Diff line number Diff line
@@ -2779,7 +2779,7 @@ public class Launcher extends StatefulActivity<LauncherState>
            View v = getFirstMatch(Collections.singletonList(activeRecyclerView),
                    preferredItem, packageAndUserAndApp);

            if (v != null && activeRecyclerView.computeVerticalScrollOffset() > 0) {
            if (v != null && activeRecyclerView.getCurrentScrollY() > 0) {
                RectF locationBounds = new RectF();
                FloatingIconView.getLocationBoundsForView(this, v, false, locationBounds,
                        new Rect());
+2 −13
Original line number Diff line number Diff line
@@ -26,9 +26,7 @@ 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;
@@ -64,10 +62,10 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends
    /**
     * A subclass of GridLayoutManager that overrides accessibility values during app search.
     */
    public class AppsGridLayoutManager extends ScrollableLayoutManager {
    public class AppsGridLayoutManager extends GridLayoutManager {

        public AppsGridLayoutManager(Context context) {
            super(context);
            super(context, 1, GridLayoutManager.VERTICAL, false);
        }

        @Override
@@ -127,15 +125,6 @@ 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
+96 −3
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
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;
@@ -24,6 +26,7 @@ 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;

@@ -46,10 +49,40 @@ 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;

    protected AlphabeticalAppsList<?> mApps;

    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();
        }
    };

    public AllAppsRecyclerView(Context context) {
        this(context, null);
@@ -89,8 +122,12 @@ 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) {
@@ -162,6 +199,17 @@ 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;
@@ -183,13 +231,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 || getChildCount() == 0) {
        if (items.isEmpty() || mNumAppsPerRow == 0) {
            mScrollbar.setThumbOffsetY(-1);
            return;
        }

        // Skip early if, there no child laid out in the container.
        int scrollY = computeVerticalScrollOffset();
        int scrollY = getCurrentScrollY();
        if (scrollY < 0) {
            mScrollbar.setThumbOffsetY(-1);
            return;
@@ -244,6 +292,51 @@ 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);
    }
+1 −2
Original line number Diff line number Diff line
@@ -103,8 +103,7 @@ 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).computeVerticalScrollOffset());
                    updateHeaderScroll(((AllAppsRecyclerView) recyclerView).getCurrentScrollY());
                }
            };

Loading