Get visible items in RecyclerView

I need to know which elements are currently displayed in my RecyclerView. There is no equivalent to the OnScrollListener.onScroll(...) method on ListViews. I tried to work with View.getGlobalVisibleRect(...), but that hack is too ugly and does not always work too.

Someone any ideas?


Solution 1:

First / last visible child depends on the LayoutManager. If you are using LinearLayoutManager or GridLayoutManager, you can use

int findFirstVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();

For example:

GridLayoutManager layoutManager = ((GridLayoutManager)mRecyclerView.getLayoutManager());
int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();

For LinearLayoutManager, first/last depends on the adapter ordering. Don't query children from RecyclerView; LayoutManager may prefer to layout more items than visible for caching.

Solution 2:

for those who have a logic to be implemented inside the RecyclerView adapter you can still use @ernesto approach combined with an on scrollListener to get what you want as the RecyclerView is consulted. Inside the adapter you will have something like this:

@Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if(manager instanceof LinearLayoutManager && getItemCount() > 0) {
            LinearLayoutManager llm = (LinearLayoutManager) manager;
            recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                }

                @Override
                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                        int visiblePosition = llm.findFirstCompletelyVisibleItemPosition();
                        if(visiblePosition > -1) {
                            View v = llm.findViewByPosition(visiblePosition);
                            //do something
                            v.setBackgroundColor(Color.parseColor("#777777"));
                        }
                }
            });
        }
    }