it-swarm.com.ru

Получить видимые элементы в RecyclerView

Мне нужно знать, какие элементы в настоящее время отображаются в моем RecyclerView. В ListViews нет эквивалента методу OnScrollListener.onScroll(...) . Я пытался работать с View.getGlobalVisibleRect(...) , но этот хак слишком уродлив и не всегда работает.

У кого-нибудь есть идеи?

221
rekire

Первый/последний видимый ребенок зависит от LayoutManager. Если вы используете LinearLayoutManager или GridLayoutManager, вы можете использовать 

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

Например:

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

Для LinearLayoutManager первый/последний зависит от заказа адаптера. Не запрашивайте детей из RecyclerView; LayoutManager может предпочесть макетировать больше элементов, чем видно для кэширования.

500
yigit

Наконец, я нашел решение узнать, является ли текущий элемент видимым, из события onBindViewHolder в адаптере.

Ключ - это метод isViewPartiallyVisible из LayoutManager.

В вашем адаптере вы можете получить LayoutManager из RecyclerView, который вы получаете в качестве параметра из события onAttachedToRecyclerView .

7
Ernesto Vega

Вы можете использовать recyclerView.getChildAt(), чтобы получить каждого видимого потомка, и установка некоторого тега convertview.setTag(index) для этих представлений в коде адаптера поможет вам связать его с данными адаптера.

4
Sreejith B Naick

Для StaggeredGridLayoutManager сделайте это:

RecyclerView rv = findViewById(...);
StaggeredGridLayoutManager lm = new StaggeredGridLayoutManager(...);
rv.setLayoutManager(lm);

И чтобы увидеть видимые элементы:

int[] viewsIds = lm.findFirstCompletelyVisibleItemPositions(null);
ViewHolder firstViewHolder = rvPlantios.findViewHolderForLayoutPosition(viewsIds[0]);
View itemView = viewHolder.itemView;

Не забудьте проверить, если он пуст.

1
Douglas Nassif Roma Junior

Следующие методы Linear / Grid LayoutManager можно использовать для проверки того, какие элементы visible

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

и если вы хотите отслеживать is item visible on screen для некоторого порога, то вы можете обратиться к следующему блогу.

https://proandroiddev.com/detecting-list-items-perceived-by-user-8f164dfb1d05

0
Sumit Jain

Приложение :

Предложенные функции findLast ... Position () do not работают правильно в сценарии со сворачивающейся панелью инструментов, когда панель инструментов развернута.

Кажется, что вид рециркулятора имеет фиксированную высоту, и, хотя панель инструментов развернута, рециркулятор перемещается вниз, частично за пределы экрана. Как следствие, результаты предложенных функций слишком высоки. Пример: последний видимый элемент называется # 9, но на самом деле элемент # 7 является последним на экране.

Это поведение также является причиной того, что моему представлению часто не удавалось прокрутить до правильной позиции, то есть scrollToPosition () не работало правильно (я наконец программно свернул панель инструментов).

0
Andreas K. aus M.

для тех, у кого есть логика, которая будет реализована в адаптере RecyclerView, вы все равно можете использовать подход @ernesto в сочетании с on scrollListener для получения what you want при обращении к RecyclerView. Внутри адаптера у вас будет что-то вроде этого:

@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"));
                        }
                }
            });
        }
    }
0
Aleyam