web-dev-qa-db-fra.com

RecyclerView - récupère tous les affichages/visionneuses existants

Je souhaite mettre à jour la RecyclerView pendant l'affichage des données. Dans mon cas, je montre des images avec ou sans étiquettes.

Par défaut, je règle la visibilité de l'étiquette lorsque je crée le détenteur de la vue et c'est très bien, mais je souhaite que l'utilisateur modifie la visibilité des étiquettes dans le menu lorsque la variable RecyclerView est affichée. Je souhaite donc mettre à jour manuellement la visibilité de toutes les vues existantes dans la RecyclerView.

Puis-je en quelque sorte obtenir tous les Views existants? J'ai besoin de tout, pas seulement des éléments visibles, je ne veux pas qu'une View recyclée plus tard ne soit pas mise à jour ...

20
prom85

En classe d'adaptateur:

Boolean isVisible = false;

public CustomAdapter(boolean isVisible) {
    this.isVisible= isVisible;
}
    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
     ...

         if (isVisible){
           //setVisibility(View.VISIBLE)
         }else{
         //setVisibility(View.INVISIBLE
         }
    }

public void updateVisibility(boolean newValue){
 isVisible= newValue;
}

Dans Activity où vous souhaitez mettre à jour la valeur où l'adaptateur est instancié:

adapter.updateVisibility(false);
adapter.notifydataSetChanged();
12
Chol

Tout d'abord, vous devez obtenir tous les index des vues affichées, puis les parcourir et utiliser le viewHolder de chaque vue:

final int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
final int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();
for (int i = firstVisibleItemPosition; i <= lastVisibleItemPosition; ++i) {
    ViewHolder holder = (ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(i);
    ...
    }

EDIT: semble ne pas toujours renvoyer tous les ViewHolders que vous voudrez peut-être gérer. Cela semble être une solution plus stable:

for (int childCount = recyclerView.getChildCount(), i = 0; i < childCount; ++i) {
   final ViewHolder holder = recyclerView.getChildViewHolder(recyclerView.getChildAt(i));
   ...
   }
53
android developer
  • La mise à jour de la taille de la liste d’adaptateur complète avec notifyDataSetChanged() n’est pas pratique.
  • Obtenir tous les enfants RecyclerView actuels (c'est-à-dire tous les éléments visibles) n'est pas suffisant: il existe des détenteurs de vue liés qui ne sont pas visibles: après le chargement au démarrage, deux ou trois éléments sont généralement liés à la dernière position visible (selon votre gestionnaire de mise en page). .

Je viens d'expérimenter en regardant les journaux que je mets, que RV lie plus d'éléments qui ne sont pas visibles, en effet je n'ai trouvé aucun moyen de les récupérer. Je me suis retrouvé à cache dans un Set ou List ces ViewHolders dans onBindViewHolder() et à uncache dans onViewRecycled():

private Set<AbstractViewHolder> mBoundViewHolders = new HashSet<>();
private int mVisibility = View.VISIBILE;

// So you can have access from the Activity/Fragment
public Set<AbstractViewHolder> getAllBoundViewHolders() {
    return Collections.unmodifiableSet(mBoundViewHolders);
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List payloads) {
    // Binding code
    ...
    holder.view.setVisibility(mVisibility);

    // Caching VH
    mBoundViewHolders.add((AbstractViewHolder) holder);
}

@Override
public void onViewRecycled(RecyclerView.ViewHolder holder) {
    // Uncaching VH
    mBoundViewHolders.remove(holder);
}

// Your method becomes
public void updateVisibility(int visibility) {
    mVisibility = visibility;
    for (AbstractViewHolder holder : mBoundViewHolders) {
        holder.updateVisibility(visibility);
    }
}

Implémentez votre interface ou votre ViewHolder abstrait afin que vous puissiez appeler votre méthode ..__ De cette manière, vous avez accès à votre contenu ViewHolder.


C’est ce que je fais dans mon FlexibleAdapter pour désélectionner les éléments sans invoquer la fonction notifyItemRangeChanged(). Et si l'utilisateur a des animations, elles sont toutes exécutées, plus les modifications d'arrière-plan aussi lorsque j'invoque ma méthode toggleActivation().

Si vous connaissez un meilleur moyen de récupérer tous les VH liés, faites-le moi savoir.

17
Davideas

Toutes les solutions ci-dessus ne donnent que les détenteurs visibles, mais en réalité, deux ou trois autres détenteurs sont liés mais non visibles. Pour obtenir également ceux-ci, la manière la plus simple et la plus précise que je puisse penser pour obtenir tous les détenteurs est la suivante:

int lastBoundHolderPosition = -1;
int lastDetachedHolderPosition = -1;

public void onBindViewHolder(final MyViewHolder holder, int position) {
    lastBoundHolderPosition = position;
    //Your implementation
}
public void onViewDetachedFromWindow(MyViewHolder holder){
    lastDetachedHolderPosition = holder.holder.getAdapterPosition();
}

Lorsque vous souhaitez que tous les adaptateurs soient visibles (plus liés, mais non visibles):

if(lastDetachedHolderPosition == -1){
    for(pos = 0; pos <= lastDetachedHolderPosition; pos++){
        ViewHolder holder = (ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(pos);
    }
}else{
    if(lastBoundHolderPosition > lastDetachedHolderPosition){ //Scroll down
        //get all the bound holders
        for(int pos = lastDetachedHolderPosition + 1; pos <= lastBoundHolderPosition; pos++){
            ViewHolder holder = (ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(pos);
        }
    }else{ //Scroll up
        //get all the bound holders
        for(int pos = lastBoundHolderPosition ; pos <= lastDetachedHolderPosition-1; pos++){
            ViewHolder holder = (ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(pos);
        }

    }
}
0
Srujan Barai