Simplemente no hay necesidad de usar bibliotecas de terceros. Un pequeño ajuste en el método demostrado en Google I / O 2016 y Heisenberg sobre este tema, es el truco.
Dado que se notifyDataSetChanged()
vuelve a dibujar el completoRecyclerView
, notifyDataItemChanged()
es una mejor opción (no la mejor) porque tenemos la posición y el ViewHolder
a nuestra disposición, y notifyDataItemChanged()
solo se vuelve a dibujar lo particular ViewHolder
en una posición determinada .
Pero el problema es que la desaparición prematura del ViewHolder
clic y su aparición no se eliminan aunque notifyDataItemChanged()
se utilicen.
El siguiente código no recurre notifyDataSetChanged()
ni notifyDataItemChanged()
se prueba en API 23 y funciona de maravilla cuando se usa en un RecyclerView donde cada ViewHolder tiene un CardView
elemento raíz:
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
es un entero global inicializado en -1.
details
es la vista completa que se muestra cuando se expande y se oculta cuando se contrae.
Como se dijo, el elemento raíz de ViewHolder
es un CardView
con foreground
y stateListAnimator
atributos definidos exactamente como lo dijo Heisenberg sobre este tema.
ACTUALIZACIÓN: La demostración anterior colapsará el elemento previamente expandido si uno de ellos está expandido. Para modificar este comportamiento y mantener el elemento expandido como está, incluso cuando se expande otro elemento, necesitará el siguiente código.
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);
ACTUALIZACIÓN: al expandir los últimos elementos de la lista, es posible que no se muestre completamente porque la parte expandida va debajo de la pantalla. Para obtener el elemento completo dentro de la pantalla, use el siguiente código.
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: Para que las demostraciones anteriores funcionen, uno debe mantener en su código una instancia de RecyclerView y su LayoutManager (el último para flexibilidad)