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 ViewHolder
zur Verfügung haben und notifyDataItemChanged()
nur das Besondere ViewHolder
an einer bestimmten Position neu zeichnen .
Das Problem ist jedoch, dass das vorzeitige Verschwinden des ViewHolder
beim 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.
details
ist die vollständige Ansicht, die beim Erweitern angezeigt und beim Reduzieren getarnt wird.
Wie gesagt, das Wurzelelement von ViewHolder
ist ein CardView
mit foreground
undstateListAnimator
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.