Il n'est tout simplement pas nécessaire d'utiliser des bibliothèques tierces. Un petit tweak dans la méthode démontrée dans Google I / O 2016 et Heisenberg sur ce sujet, fait l'affaire.
Depuis notifyDataSetChanged() redessine le completRecyclerView , notifyDataItemChanged()est une meilleure option (pas la meilleure) car nous avons la position et le ViewHolderà notre disposition, et notifyDataItemChanged()seulement redessine le particulier ViewHolderà une position donnée .
Mais le problème est que la disparition prématurée du ViewHolder clic et son émergence n'est pas éliminée même si elle notifyDataItemChanged()est utilisée.
Le code suivant ne recourt pas à notifyDataSetChanged()ou notifyDataItemChanged()et est testé sur l'API 23 et fonctionne comme un charme lorsqu'il est utilisé sur un RecyclerView où chaque ViewHolder a un CardViewélément racine:
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final boolean visibility = holder.details.getVisibility()==View.VISIBLE;
if (!visibility)
{
holder.itemView.setActivated(true);
holder.details.setVisibility(View.VISIBLE);
if (prev_expanded!=-1 && prev_expanded!=position)
{
recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.setActivated(false);
recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.findViewById(R.id.cpl_details).setVisibility(View.GONE);
}
prev_expanded = position;
}
else
{
holder.itemView.setActivated(false);
holder.details.setVisibility(View.GONE);
}
TransitionManager.beginDelayedTransition(recycler);
}
});
prev_position est un entier global initialisé à -1.
detailsest la vue complète qui est affichée lorsqu'elle est développée et masquée lorsqu'elle est réduite.
Comme dit, l'élément racine de ViewHolderest un CardViewavec foregroundet des stateListAnimatorattributs définis exactement comme l'a dit Heisenberg sur ce sujet.
MISE À JOUR: La démonstration ci-dessus réduira l'élément déjà développé si l'un d'entre eux est développé. Pour modifier ce comportement et conserver un élément développé tel quel, même lorsqu'un autre élément est développé, vous aurez besoin du code suivant.
if (row.details.getVisibility()!=View.VISIBLE)
{
row.details.setVisibility(View.VISIBLE);
row.root.setActivated(true);
row.details.animate().alpha(1).setStartDelay(500);
}
else
{
row.root.setActivated(false);
row.details.setVisibility(View.GONE);
row.details.setAlpha(0);
}
TransitionManager.beginDelayedTransition(recycler);
MISE À JOUR: Lorsque vous développez les derniers éléments de la liste, il se peut que la visibilité totale ne soit pas visible car la partie développée passe sous l'écran. Pour obtenir l'élément complet dans l'écran, utilisez le code suivant.
LinearLayoutManager manager = (LinearLayoutManager) recycler.getLayoutManager();
int distance;
View first = recycler.getChildAt(0);
int height = first.getHeight();
int current = recycler.getChildAdapterPosition(first);
int p = Math.abs(position - current);
if (p > 5) distance = (p - (p - 5)) * height;
else distance = p * height;
manager.scrollToPositionWithOffset(position, distance);
IMPORTANT: pour que les démonstrations ci-dessus fonctionnent, il faut conserver dans leur code une instance de RecyclerView et de son LayoutManager (le plus récent pour plus de flexibilité)