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.
details
est 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 ViewHolder
est un CardView
avec foreground
et des stateListAnimator
attributs 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é)