Semplicemente non è necessario utilizzare librerie di terze parti. Un piccolo trucco nel metodo dimostrato in Google I / O 2016 e Heisenberg su questo argomento, fa il trucco.
Dal momento che notifyDataSetChanged()
ridisegna il completoRecyclerView
, notifyDataItemChanged()
è una scelta migliore (non il migliore) perché abbiamo la posizione e la ViewHolder
a nostra disposizione, e notifyDataItemChanged()
solo ridisegna il particolare ViewHolder
in una determinata posizione .
Ma il problema è che la scomparsa prematura del ViewHolder
clic e della sua comparsa non viene eliminata anche se notifyDataItemChanged()
viene utilizzata.
Il codice seguente non ricorre a notifyDataSetChanged()
o notifyDataItemChanged()
ed è testato su API 23 e funziona come un incantesimo quando utilizzato su un RecyclerView in cui ogni ViewHolder ha un CardView
elemento radice:
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
è un numero intero globale inizializzato su -1.
details
è la vista completa che viene mostrata quando espansa e occultata quando viene compressa.
Come detto, l'elemento radice di ViewHolder
è un CardView
con foreground
e stateListAnimator
attributi definiti esattamente come detto da Heisenberg su questo argomento.
AGGIORNAMENTO: la dimostrazione precedente comprimerà l'elemento espanso in precedenza se uno di essi viene espanso. Per modificare questo comportamento e mantenere un elemento espanso così com'è anche quando viene espanso un altro elemento, è necessario il seguente codice.
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);
AGGIORNAMENTO: quando si espandono gli ultimi elementi dell'elenco, potrebbe non essere portato alla piena visibilità perché la parte espansa va sotto lo schermo. Per visualizzare l'intero elemento sullo schermo, utilizzare il seguente codice.
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);
IMPORTANTE: affinché le dimostrazioni di cui sopra funzionino, è necessario conservare nel proprio codice un'istanza di RecyclerView ed è LayoutManager (la versione successiva per flessibilità)