J'ai besoin de savoir quels éléments sont actuellement affichés dans mon RecyclerView. Il n'y a pas d'équivalent à la méthode OnScrollListener.onScroll(...)
sur ListViews. J'ai essayé de travailler avec View.getGlobalVisibleRect(...)
, mais ce bidouillage est trop moche et ne fonctionne pas toujours aussi.
Quelqu'un a des idées?
Le premier/dernier enfant visible dépend de la LayoutManager
. Si vous utilisez LinearLayoutManager
ou GridLayoutManager
, vous pouvez utiliser
int findFirstVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();
Par exemple:
GridLayoutManager layoutManager = ((GridLayoutManager)mRecyclerView.getLayoutManager());
int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();
Pour LinearLayoutManager
, first/last dépend de la commande de l’adaptateur. N'interrogez pas les enfants de RecyclerView
; LayoutManager
peut préférer disposer plus d'éléments que visibles pour la mise en cache.
Enfin, j'ai trouvé une solution pour savoir si l'élément actuel est visible, à partir de l'événement onBindViewHolder de l'adaptateur.
La clé est la méthode isViewPartiallyVisible de LayoutManager.
Dans votre adaptateur, vous pouvez obtenir LayoutManager à partir de RecyclerView, que vous obtenez comme paramètre à partir de onAttachedToRecyclerView event.
Vous pouvez utiliser recyclerView.getChildAt()
pour obtenir chaque enfant visible et définir quelques balises convertview.setTag(index)
sur ces vues dans le code de l'adaptateur vous aidera à les associer aux données de l'adaptateur.
Pour StaggeredGridLayoutManager
faire ceci:
RecyclerView rv = findViewById(...);
StaggeredGridLayoutManager lm = new StaggeredGridLayoutManager(...);
rv.setLayoutManager(lm);
Et pour obtenir des vues d'élément visibles:
int[] viewsIds = lm.findFirstCompletelyVisibleItemPositions(null);
ViewHolder firstViewHolder = rvPlantios.findViewHolderForLayoutPosition(viewsIds[0]);
View itemView = viewHolder.itemView;
N'oubliez pas de vérifier s'il est vide.
Les méthodes Linear / Grid LayoutManager
suivantes peuvent être utilisées pour vérifier quels éléments sont visible
int findFirstVisibleItemPosition();
int findLastVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();
et si vous souhaitez suivre is item visible on screen
pour un certain seuil, vous pouvez vous reporter au blog suivant.
https://proandroiddev.com/detecting-list-items-perceived-by-user-8f164dfb1d05
Addenda :
Les fonctions proposées findLast ... Position () do not ne fonctionnent pas correctement dans un scénario avec une barre d'outils réductrice tant que la barre d'outils est développée.
Il semble que la vue du recycleur ait une hauteur fixe et que tant que la barre d’outils est étendue, le recycleur est déplacé vers le bas, partiellement en dehors de l’écran. En conséquence, les résultats des fonctions proposées sont trop élevés. Exemple: le dernier élément visible est n ° 9, mais en réalité, le n ° 7 est le dernier élément affiché à l'écran.
Ce comportement est également la raison pour laquelle mon point de vue ne permet souvent pas de faire défiler l'écran jusqu'à la position correcte, c'est-à-dire que scrollToPosition () ne fonctionne pas correctement (j'ai finalement réduit la barre d'outils par programme).
pour ceux qui souhaitent implémenter une logique dans l'adaptateur RecyclerView, vous pouvez toujours utiliser l'approche @ernesto combinée à un scrollListener pour obtenir what you want
lors de la consultation de RecyclerView. À l'intérieur de l'adaptateur, vous aurez quelque chose comme ça:
@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"));
}
}
});
}
}