Po prostu nie ma potrzeby korzystania z bibliotek innych firm. Trochę uszczypnąć w metodzie wykazano w Google I / O 2016 i Heisenberga na ten temat, załatwia sprawę.
Ponieważ notifyDataSetChanged()
przerysowuje w całościRecyclerView
, notifyDataItemChanged()
jest lepszą opcją (nie najlepszą), ponieważ mamy pozycję i do ViewHolder
dyspozycji, a notifyDataItemChanged()
tylko przerysowuje konkret ViewHolder
na danej pozycji .
Problem polega jednak na tym, że przedwczesne zniknięcie ViewHolder
po kliknięciu i jego pojawienie się nie jest wyeliminowane, nawet jeśli notifyDataItemChanged()
jest używane.
Poniższy kod nie odwołuje się do notifyDataSetChanged()
ani notifyDataItemChanged()
i jest testowany na interfejsie API 23 i działa jak urok, gdy jest używany w RecyclerView, gdzie każdy element ViewHolder ma CardView
jako element główny:
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
jest globalną liczbą całkowitą zainicjowaną na -1.
details
to pełny widok, który jest wyświetlany po rozwinięciu i zasłonięciu po zwinięciu.
Jak powiedziano, głównym elementem ViewHolder
jest atrybut a CardView
with foreground
i stateListAnimator
zdefiniowane dokładnie tak, jak powiedział Heisenberg na ten temat.
AKTUALIZACJA: Powyższa demonstracja zwinie wcześniej rozwinięty element, jeśli jeden z nich zostanie rozwinięty. Aby zmodyfikować to zachowanie i zachować rozwinięty element w takim stanie, w jakim jest nawet po rozwinięciu innego elementu, potrzebujesz następującego kodu.
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);
AKTUALIZACJA: Podczas rozwijania ostatnich elementów na liście, może nie być ona w pełni widoczna, ponieważ rozwinięta część znajduje się poniżej ekranu. Aby uzyskać pełną pozycję na ekranie, użyj następującego kodu.
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);
WAŻNE: Aby powyższe demonstracje działały, należy zachować w swoim kodzie wystąpienie RecyclerView i jego LayoutManager (później dla elastyczności)