Obtener elementos visibles en RecyclerView
Necesito saber qué elementos se muestran actualmente en mi RecyclerView. No existe un equivalente al OnScrollListener.onScroll(...)
método en ListViews. Intenté trabajar conView.getGlobalVisibleRect(...)
, pero ese truco es demasiado feo y no siempre funciona.
¿Alguien tiene alguna idea?
El primer/último hijo visible depende del LayoutManager
. Si estás usando LinearLayoutManager
o GridLayoutManager
, puedes usar
int findFirstVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();
Por ejemplo:
GridLayoutManager layoutManager = ((GridLayoutManager)mRecyclerView.getLayoutManager());
int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();
Para LinearLayoutManager
, primero/último depende del pedido del adaptador. No consulte a los niños de RecyclerView
; LayoutManager
Es posible que prefiera diseñar más elementos de los visibles para el almacenamiento en caché.
Para aquellos que tienen una lógica para implementar dentro del adaptador RecyclerView, aún pueden usar el enfoque @ernesto combinado con un scrollListener para obtener what you want
cómo se consulta RecyclerView. Dentro del adaptador tendrás algo como esto:
@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"));
}
}
});
}
}
Finalmente, encontré una solución para saber si el elemento actual es visible, desde el evento onBindViewHolder en el adaptador.
La clave es el método isViewPartiallyVisible de LayoutManager.
En su adaptador, puede obtener LayoutManager de RecyclerView, que obtiene como parámetro del evento onAttachedToRecyclerView .
Todas las respuestas anteriores son correctas y me gustaría agregar también una instantánea de mis códigos de trabajo.
recycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
// Some code when initially scrollState changes
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// Some code while the list is scrolling
LinearLayoutManager lManager = (LinearLayoutManager) recyclerView.getLayoutManager();
int firstElementPosition = lManager.findFirstVisibleItemPosition();
}
});
Puede usarlo recyclerView.getChildAt()
para obtener cada hijo visible y configurar alguna etiqueta convertview.setTag(index)
en estas vistas en el código del adaptador lo ayudará a relacionarlo con los datos del adaptador.