web-dev-qa-db-fra.com

Obtenir des éléments visibles dans RecyclerView

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?

221
rekire

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.

500
yigit

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.

7
Ernesto Vega

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.

4
Sreejith B Naick

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

0
Sumit Jain

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).

0

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