Von https://developer.android.com/preview/material/ui-widgets.html
Beim Erstellen müssen RecyclerView.Adapter
wir angeben, ViewHolder
dass die Bindung an den Adapter erfolgt.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private String[] mDataset;
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ViewHolder(TextView v) {
super(v);
mTextView = v;
}
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.some_layout, parent, false);
//findViewById...
ViewHolder vh = new ViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTextView.setText(mDataset[position]);
}
@Override
public int getItemCount() {
return mDataset.length;
}
}
Ist es also möglich, RecyclerView
mit mehreren Ansichtstypen zu erstellen ?
Antworten:
Ja es ist möglich. Implementieren Sie einfach getItemViewType () und kümmern Sie sich um den
viewType
Parameter inonCreateViewHolder()
.Also machst du so etwas wie:
quelle
optionMenuItem
. Wie ist es möglich? @ AntonSavinWenn es nur wenige Layouts für Ansichtstypen gibt und die Bindungslogik einfach ist, befolgen Sie die Lösung von Anton.
Der Code ist jedoch unübersichtlich, wenn Sie die komplexen Layouts und Bindungslogiken verwalten müssen.
Ich glaube, die folgende Lösung ist nützlich für jemanden, der komplexe Ansichtstypen verarbeiten muss.
Basis-DataBinder-Klasse
Die Funktionen, die zum Definieren in dieser Klasse erforderlich sind, entsprechen weitgehend denen der Adapterklasse beim Erstellen des Einzelansichtstyps.
Erstellen Sie für jeden Ansichtstyp die Klasse, indem Sie diesen DataBinder erweitern.
Beispiel für eine DataBinder-Klasse
Erstellen Sie eine Adapterklasse, um DataBinder-Klassen zu verwalten.
Basis DataBindAdapter-Klasse
Erstellen Sie die Klasse, indem Sie diese Basisklasse erweitern, und instanziieren Sie dann DataBinder-Klassen und überschreiben Sie abstrakte Methoden
getItemCount Gibt
die Gesamtzahl der Artikel von DataBinders zurück
getItemViewType
Definieren Sie die Zuordnungslogik zwischen Adapterposition und Ansichtstyp.
getDataBinder Gibt
die DataBinder-Instanz basierend auf dem Ansichtstyp zurück
getPosition
Definieren Sie die Konvertierungslogik von der Position im angegebenen DataBinder in die Adapterposition
getBinderPosition
Definieren Sie die Konvertierungslogik von der Adapterposition in die Position im DataBinder
Hoffe, diese Lösung wird hilfreich sein.
Ich habe detailliertere Lösungen und Beispiele in GitHub hinterlassen. Bitte verweisen Sie bei Bedarf auf den folgenden Link.
https://github.com/yqritc/RecyclerView-MultipleViewTypesAdapter
quelle
public class DataBinder<T extends RecyclerView.ViewHolder>
kann mir jemand sagen, wie<T someClass>
es heißt, damit ich googeln kann, wenn ich den Begriff bekomme. Auch wenn ich sage,abstract public class DataBinder<T extends RecyclerView.ViewHolder>
bedeutet das, dass diese Klasse vom Typ istViewHolder
, so dass im Ergebnis jede Klasse, die diese Klasse erweitert, vom TypviewHolder
ist, ist das die Idee?Das Folgende ist kein Pseudocode und ich habe es getestet und es hat für mich funktioniert.
Ich wollte eine Kopfansicht in meiner Recyclingansicht erstellen und dann eine Liste mit Bildern unter der Kopfzeile anzeigen, auf die der Benutzer klicken kann.
Ich habe einige Schalter in meinem Code verwendet. Ich weiß nicht, ob dies der effizienteste Weg ist. Geben Sie also Ihre Kommentare ab:
quelle
Ja, es ist möglich.
Schreiben Sie einen generischen Ansichtsinhaber:
Erstellen Sie dann Ihre Ansichtshalter und erweitern Sie den GenericViewHolder. Zum Beispiel dieses:
dann sieht die RecyclerView.Adapter-Klasse folgendermaßen aus:
quelle
Erstellen Sie unterschiedliche ViewHolder für unterschiedliche Layouts
RecyclerView kann eine beliebige Anzahl von Ansichtsinhabern haben. Zur besseren Lesbarkeit können Sie jedoch sehen, wie Sie einen mit zwei ViewHoldern erstellen.
public int getItemViewType(int position)
onCreateViewHolder()
Methode zurückonBindViewHolder()
Methode itemViewType inHier ist ein kleiner Code-Ausschnitt
getItemViewType (int position) ist der Schlüssel
Meiner Meinung nach ist der Ausgangspunkt für die Erstellung dieser Art von recyclerView das Wissen über diese Methode. Da diese Methode optional überschrieben werden kann, ist sie in der RecylerView-Klasse standardmäßig nicht sichtbar, was wiederum viele Entwickler (einschließlich mich) dazu bringt, sich zu fragen, wo sie anfangen sollen. Sobald Sie wissen, dass diese Methode vorhanden ist, wäre das Erstellen einer solchen RecyclerView ein Kinderspiel.
Relevante Links:
Schauen Sie sich das Projekt an, in dem ich dies implementiert habe
quelle
Ja, es ist möglich. In Ihrem Adapter getItemViewType Layout wie folgt ....
Als Referenzlink: https://www.journaldev.com/12372/android-recyclerview-example
quelle
Überlegen Sie sich nach Antons Lösung Folgendes,
ViewHolder
das verschiedene Arten von Layouts enthält / verarbeitet / delegiert. Sie sind sich jedoch nicht sicher, ob das Ersetzen eines neuen Layouts funktionieren würde, wenn die RecyclingansichtViewHolder
nicht der Typ der Daten ist, die eingegeben werden.Wird also grundsätzlich
onCreateViewHolder(ViewGroup parent, int viewType)
nur aufgerufen, wenn ein neues Ansichtslayout benötigt wird;getItemViewType(int position)
wird für die gerufenviewType
;onBindViewHolder(ViewHolder holder, int position)
wird immer aufgerufen, wenn die Ansicht recycelt wird (neue Daten werden eingegeben und versuchen, damit anzuzeigenViewHolder
).Wenn
onBindViewHolder
es aufgerufen wird, muss es das richtige Ansichtslayout einfügen und das aktualisierenViewHolder
.Ist der Weg zum Ersetzen des Ansichtslayouts für das Einbringen korrekt
ViewHolder
oder ein Problem? Schätzen Sie jeden Kommentar!Bearbeiten: ViewHolder hat das Mitglied mItemViewType, um die Ansicht zu halten
Bearbeiten: sieht so aus, als ob in onBindViewHolder (ViewHolder-Inhaber, int-Position) der übergebene ViewHolder von getItemViewType (int-Position) aufgenommen (oder erstellt) wurde, um sicherzustellen, dass es sich um eine Übereinstimmung handelt, sodass Sie sich dort möglicherweise keine Sorgen um ViewHolder machen müssen Typ stimmt nicht mit dem Datentyp [Position] überein. Weiß jemand mehr darüber, wie der ViewHolder im onBindViewHolder () aufgenommen wird?
Bearbeiten: Sieht aus wie Das Recycling
ViewHolder
wird nach Typ ausgewählt, also kein Krieger dort.Bearbeiten: http://wiresareobsolete.com/2014/09/building-a-recyclerview-layoutmanager-part-1/ beantwortet diese Frage.
Es wird recycelt
ViewHolder
wie:oder erstellen Sie eine neue, wenn Sie nicht das
ViewHolder
richtige Recycling finden .quelle
Ich habe eine bessere Lösung, mit der mehrere Ansichtstypen deklarativ und typsicher erstellt werden können. Es ist in Kotlin geschrieben, was übrigens wirklich nett ist.
Einfache Ansichtshalter für alle erforderlichen Ansichtstypen
Es gibt eine Abstraktion des Adapterdatenelements. Beachten Sie, dass ein Ansichtstyp durch einen Hashcode einer bestimmten Ansichtsinhaberklasse dargestellt wird (KClass in Kotlin).
Nur
bindViewHolder
muss in Beton Adapter Elementklassen (Typen sichere Art und Weise) außer Kraft gesetzt werden ,Die Liste solcher
AdapterItemMedium
Objekte ist eine Datenquelle für den Adapter, die tatsächlich akzeptiert,List<AdapterItem>
siehe unten.Ein wichtiger Teil dieser Lösung ist eine View Holder Factory, die neue Instanzen eines bestimmten ViewHolder bereitstellt
Und die einfache Adapterklasse sieht so aus
Nur 3 Schritte zum Erstellen eines neuen Ansichtstyps:
ViewHolderProvider
Hier ist ein Beispiel für dieses Konzept: android-drawer-template Es geht noch weiter - Ansichtstyp, der als Spinner-Komponente fungiert, auswählbare Adapterelemente.
quelle
Es ist sehr einfach und unkompliziert.
Überschreiben Sie nur getItemViewType () Methode in Ihrem Adapter. Auf Basis der Daten werden unterschiedliche itemViewType-Werte zurückgegeben. Beispiel: Betrachten Sie ein Objekt vom Typ Person mit einem Mitglied isMale. Wenn isMale true ist, geben Sie 1 zurück und isMale ist false, geben Sie 2 in der Methode getItemViewType () zurück .
Kommen wir nun zum createViewHolder (ViewGroup-Eltern, int viewType) , auf der Grundlage eines anderen viewType können Sie die verschiedenen Layoutdateien aufblasen. wie das folgende
Überprüfen Sie in onBindViewHolder (VH-Inhaber, int-Position) , wo der Inhaber eine Instanz von
AdapterFemaleViewHolder
oderAdapterMaleViewHolder
von ist,instanceof
und weisen Sie die Werte entsprechend zu.ViewHolder Kann so sein
quelle
Obwohl die ausgewählte Antwort korrekt ist, möchte ich sie nur weiter ausführen. Ich habe hier einen nützlichen benutzerdefinierten Adapter für mehrere Ansichtstypen in RecyclerView gefunden . Die Kotlin-Version ist da .
Benutzerdefinierter Adapter folgt
quelle
Ich empfehle diese Bibliothek von Hannes Dorfmann. Es kapselt die gesamte Logik für einen bestimmten Ansichtstyp in einem separaten Objekt namens "AdapterDelegate". https://github.com/sockeqwe/AdapterDelegates
quelle
Eigentlich möchte ich Antons Antwort verbessern .
Da
getItemViewType(int position)
ein ganzzahliger Wert zurückgegeben wird, können Sie die Layout-Ressourcen-ID zurückgeben, die Sie aufblasen müssen. Auf diese Weise würden Sie eine Logik in deronCreateViewHolder(ViewGroup parent, int viewType)
Methode speichern .Außerdem würde ich nicht empfehlen, intensive Berechnungen durchzuführen,
getItemCount()
da diese bestimmte Funktion beim Rendern der Liste sowie beim Rendern jedes Elements über die sichtbaren Elemente hinaus mindestens fünfmal aufgerufen wird. Da dienotifyDatasetChanged()
Methode endgültig ist, können Sie sie leider nicht wirklich überschreiben, aber Sie können sie von einer anderen Funktion im Adapter aus aufrufen.quelle
Note: Integers must be in the range 0 to getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPE can also be returned.
Es ist also besser, etwas mehr Code zu schreiben und keine Hacks zu verwenden.Sie können die Bibliothek verwenden: https://github.com/vivchar/RendererRecyclerViewAdapter
`
Für jedes Element sollten Sie einen ViewRenderer, ViewHolder, SomeModel implementieren:
ViewHolder - ist ein einfacher Ansichtshalter für die Recycler-Ansicht.
SomeModel - es ist Ihr Modell mit
ItemModel
SchnittstelleWeitere Informationen finden Sie in den Dokumentationen.
quelle
Die Implementierung von Ansichtstypen wird mit kotlin einfacher. Hier ist ein Beispiel mit dieser Lichtbibliothek https://github.com/Link184/KidAdapter
quelle
Sie können mehrere
RecyclerAdapter
ViewTypes verarbeiten, indem SiegetItemViewType()
den erwartetenviewType
Wert für diese Position zurückgebenIch habe eine
MultipleViewTypeAdapter
MCQ-Liste für Prüfungen erstellt, die möglicherweise eine Frage mit zwei oder mehr gültigen Antworten (Kontrollkästchenoptionen) und eine einzelne Antwortfrage (Radiobutton-Optionen) enthält.Dafür erhalte ich die Art der Frage aus der API-Antwort und habe diese verwendet, um zu entscheiden, welche Ansicht ich für diese Frage anzeigen muss.
Sie können das Ausfüllen mehrerer bedingter viewHolder-Daten vermeiden,
onBindViewHolder()
indem Sie dieselben IDs für ähnliche Ansichten in viewHolders zuweisen, die sich in ihrer Positionierung unterscheiden.quelle
Wenn Sie es in Verbindung mit Android Data Binding verwenden möchten, schauen Sie in den https://github.com/evant/binding-collection-adapter - es ist bei weitem die beste Lösung für die verschiedenen Ansichtstypen, die
RecyclerView
ich je gesehen habe.Sie können es wie verwenden
und dann im Layout, wo die Liste ist
Ihre Listenelemente müssen eine
BaseListItem
Schnittstelle implementieren , die so aussiehtund die Objektansicht sollte ungefähr so aussehen
Wo
YourListItem
implementiertBaseListItem
Hoffe es wird jemandem helfen.
quelle
Zuerst müssen Sie 2 Layout-XML erstellen. Danach sind im Recyclerview-Adapter TYPE_CALL und TYPE_EMAIL zwei statische Werte mit 1 bzw. 2 in der Adapterklasse.
Definieren Sie jetzt zwei statische Werte auf der Ebene der Adapterklasse der Recycler-Ansicht: private static int TYPE_CALL = 1; private static int TYPE_EMAIL = 2;
Erstellen Sie nun einen Ansichtshalter mit mehreren Ansichten wie folgt:
Codieren Sie nun wie folgt in den Methoden onCreateViewHolder und onBindViewHolder im recyclerview-Adapter:
quelle