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 ...
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();
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));
...
}
notifyDataSetChanged()
n’est pas pratique.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.
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);
}
}
}