Es ist einfach nicht erforderlich, Bibliotheken von Drittanbietern zu verwenden. Eine kleine Änderung an der in Google I / O 2016 demonstrierten Methode und Heisenberg zu diesem Thema vorgestellten reicht aus.
Da das notifyDataSetChanged() Ganze neu gezeichnet wirdRecyclerView , notifyDataItemChanged()ist dies eine bessere Option (nicht die beste), da wir die Position und das ViewHolderzur Verfügung haben und notifyDataItemChanged()nur das Besondere ViewHolderan einer bestimmten Position neu zeichnen .
Das Problem ist jedoch, dass das vorzeitige Verschwinden des ViewHolderbeim Klicken und dessen Auftreten nicht beseitigt wird, selbst wennnotifyDataItemChanged() es verwendet wird.
Der folgende Code greift nicht auf notifyDataSetChanged()oder zurück notifyDataItemChanged()und wird auf API 23 getestet und funktioniert wie ein Zauber, wenn er in einer RecyclerView verwendet wird, in der jeder ViewHolder ein Stammelement hat CardView:
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 ist eine globale Ganzzahl, die mit -1 initialisiert ist.
detailsist die vollständige Ansicht, die beim Erweitern angezeigt und beim Reduzieren getarnt wird.
Wie gesagt, das Wurzelelement von ViewHolderist ein CardViewmit foregroundundstateListAnimator Attribute, die genau so definiert sind, wie es Heisenberg zu diesem Thema gesagt hat.
UPDATE: Die obige Demonstration wird das zuvor erweiterte Element reduzieren, wenn eines davon erweitert wird. Um dieses Verhalten zu ändern und das erweiterte Element so zu belassen, wie es ist, auch wenn ein anderes Element erweitert wird, benötigen Sie den folgenden Code.
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);
UPDATE: Wenn Sie die letzten Elemente in der Liste erweitern, wird sie möglicherweise nicht vollständig sichtbar, da der erweiterte Bereich unter dem Bildschirm angezeigt wird. Verwenden Sie den folgenden Code, um das vollständige Element auf dem Bildschirm anzuzeigen.
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);
WICHTIG: Damit die oben genannten Demonstrationen funktionieren, muss eine Instanz von RecyclerView und dessen LayoutManager (der spätere aus Gründen der Flexibilität) in ihrem Code gespeichert werden.