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

Commit eb367e47 authored by Stevie Kideckel's avatar Stevie Kideckel
Browse files

Scroll to the selected widget picker row after headers are clicked

This keeps the row in view. Currently, this will scroll the row to the
centre-bottom of the screen due to the top padding being double counted,
but that will remedied in a future CL.

This also resolves the issue where the last row's widgets aren't visible
by handling that case specially

Fix: 188665456
Bug: 183378651
Test: verified locally
Change-Id: I9acb9087a8cdaf130ac5955c810c96462b368f36
parent a4adcbc8
Loading
Loading
Loading
Loading
+51 −4
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.TableRow;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.Adapter;
@@ -48,8 +49,10 @@ import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.OptionalInt;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * Recycler view adapter for the widget tray.
@@ -87,6 +90,7 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
                    || new PackageUserKey(entry.mPkgItem.packageName, entry.mPkgItem.user)
                            .equals(mWidgetsContentVisiblePackageUserKey);
    @Nullable private Predicate<WidgetsListBaseEntry> mFilter = null;
    @Nullable private RecyclerView mRecyclerView;

    public WidgetsListAdapter(Context context, LayoutInflater layoutInflater,
            WidgetPreviewLoader widgetPreviewLoader, IconCache iconCache,
@@ -106,6 +110,16 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
                        layoutInflater, /*onHeaderClickListener=*/ this, /* listAdapter= */ this));
    }

    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
    }

    @Override
    public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
        mRecyclerView = null;
    }

    public void setFilter(Predicate<WidgetsListBaseEntry> filter) {
        mFilter = filter;
    }
@@ -168,12 +182,10 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
        mAllEntries.forEach(entry -> {
            if (entry instanceof WidgetsListHeaderEntry) {
                ((WidgetsListHeaderEntry) entry).setIsWidgetListShown(
                        new PackageUserKey(entry.mPkgItem.packageName, entry.mPkgItem.user)
                                .equals(mWidgetsContentVisiblePackageUserKey));
                        isHeaderForVisibleContent(entry));
            } else if (entry instanceof WidgetsListSearchHeaderEntry) {
                ((WidgetsListSearchHeaderEntry) entry).setIsWidgetListShown(
                        new PackageUserKey(entry.mPkgItem.packageName, entry.mPkgItem.user)
                                .equals(mWidgetsContentVisiblePackageUserKey));
                        isHeaderForVisibleContent(entry));
            }
        });
        List<WidgetsListBaseEntry> newVisibleEntries = mAllEntries.stream()
@@ -183,6 +195,13 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
        mDiffReporter.process(mVisibleEntries, newVisibleEntries, mRowComparator);
    }

    private boolean isHeaderForVisibleContent(WidgetsListBaseEntry entry) {
        return (entry instanceof WidgetsListHeaderEntry
                || entry instanceof WidgetsListSearchHeaderEntry)
                && new PackageUserKey(entry.mPkgItem.packageName, entry.mPkgItem.user)
                .equals(mWidgetsContentVisiblePackageUserKey);
    }

    /**
     * Resets any expanded widget header.
     */
@@ -247,12 +266,40 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
        if (showWidgets) {
            mWidgetsContentVisiblePackageUserKey = packageUserKey;
            updateVisibleEntries();
            // Scroll the layout manager to the header position to keep it anchored to the same
            // position.
            scrollToSelectedHeaderPosition();
        } else if (packageUserKey.equals(mWidgetsContentVisiblePackageUserKey)) {
            mWidgetsContentVisiblePackageUserKey = null;
            updateVisibleEntries();
        }
    }

    private void scrollToSelectedHeaderPosition() {
        OptionalInt selectedHeaderPosition =
                IntStream.range(0, mVisibleEntries.size())
                        .filter(index -> isHeaderForVisibleContent(mVisibleEntries.get(index)))
                        .findFirst();
        RecyclerView.LayoutManager layoutManager =
                mRecyclerView == null ? null : mRecyclerView.getLayoutManager();
        if (!selectedHeaderPosition.isPresent() || layoutManager == null) {
            return;
        }

        // Scroll to the selected header position. LinearLayoutManager scrolls the minimum distance
        // necessary, so this will keep the selected header in place during clicks, without
        // interrupting the animation.
        int position = selectedHeaderPosition.getAsInt();
        if (position == mVisibleEntries.size() - 2) {
            // If the selected header is in the last position (-1 for the content), then scroll to
            // the final position so the last list of widgets will show.
            layoutManager.scrollToPosition(mVisibleEntries.size() - 1);
        } else {
            // Otherwise, scroll to the position of the selected header.
            layoutManager.scrollToPosition(position);
        }
    }

    /**
     * Sets the max horizontal spans that are allowed for grouping more than one widgets in a table
     * row.