Dynamische Listen mit RecyclerView erstellen Teil von Android Jetpack.
Mit RecyclerView lassen sich große Datenmengen effizient darstellen. Sie stellen die Daten bereit und definieren, wie die einzelnen Elemente aussehen sollen. Die RecyclerView-Bibliothek erstellt die Elemente dann dynamisch, wenn sie benötigt werden.
Wie der Name schon sagt, werden die einzelnen Elemente in RecyclerView wiederverwendet. Wenn ein Element vom Bildschirm scrollt, wird seine Ansicht von RecyclerView nicht zerstört. Stattdessen wird die Ansicht für neue Elemente wiederverwendet, die auf dem Bildschirm angezeigt werden. RecyclerView verbessert die Leistung und Reaktionsfähigkeit Ihrer App und reduziert den Stromverbrauch.
Wichtige Klassen
Mehrere Klassen arbeiten zusammen, um Ihre dynamische Liste zu erstellen.
RecyclerView
ist dieViewGroup
, die die Ansichten für Ihre Daten enthält. Es handelt sich um eine Ansicht, daher fügen SieRecyclerView
Ihrem Layout auf dieselbe Weise hinzu wie jedes andere UI-Element.Jedes einzelne Element in der Liste wird durch ein View-Holder-Objekt definiert. Wenn der View-Holder erstellt wird, sind ihm keine Daten zugeordnet. Nachdem der Ansichtshalter erstellt wurde, bindet
RecyclerView
ihn an seine Daten. Sie definieren den View-Holder, indem SieRecyclerView.ViewHolder
erweitern.Die
RecyclerView
-Klasse fordert Ansichten an und bindet sie an ihre Daten, indem sie Methoden im Adapter aufruft. Sie definieren den Adapter, indem SieRecyclerView.Adapter
erweitern.Der Layout-Manager ordnet die einzelnen Elemente in Ihrer Liste an. Sie können einen der von der RecyclerView-Bibliothek bereitgestellten Layoutmanager verwenden oder einen eigenen definieren. Alle Layoutmanager basieren auf der abstrakten Klasse
LayoutManager
der Bibliothek.
Wie alles zusammenpasst, sehen Sie in der RecyclerView-Beispiel-App (Kotlin) oder der RecyclerView-Beispiel-App (Java).
Schritte zum Implementieren von RecyclerView
Wenn Sie RecyclerView verwenden möchten, müssen Sie einige Dinge tun. Diese werden in den folgenden Abschnitten ausführlich erläutert.
Legen Sie fest, wie die Liste oder das Raster aussehen soll. Normalerweise können Sie einen der Standard-Layout-Manager der RecyclerView-Bibliothek verwenden.
Legen Sie fest, wie die einzelnen Elemente in der Liste aussehen und sich verhalten sollen. Erweitern Sie die Klasse
ViewHolder
basierend auf diesem Design. Ihre Version vonViewHolder
bietet alle Funktionen für Ihre Listenelemente. Der View-Holder ist ein Wrapper um einView
und diese Ansicht wird vonRecyclerView
verwaltet.Definieren Sie die
Adapter
, mit der Ihre Daten denViewHolder
-Ansichten zugeordnet werden.
Es gibt auch erweiterte Anpassungsoptionen, mit denen Sie Ihren RecyclerView genau an Ihre Anforderungen anpassen können.
Layout planen
Die Elemente in Ihrer RecyclerView werden von einer LayoutManager
-Klasse angeordnet. Die RecyclerView-Bibliothek bietet drei Layoutmanager, die die häufigsten Layoutsituationen abdecken:
LinearLayoutManager
ordnet die Elemente in einer eindimensionalen Liste an.GridLayoutManager
ordnet die Elemente in einem zweidimensionalen Raster an:- Wenn das Raster vertikal angeordnet ist, versucht
GridLayoutManager
, alle Elemente in jeder Zeile auf dieselbe Breite und Höhe einzustellen. Die Zeilen können jedoch unterschiedliche Höhen haben. - Wenn das Raster horizontal angeordnet ist, versucht
GridLayoutManager
, alle Elemente in jeder Spalte auf dieselbe Breite und Höhe einzustellen. Die Spalten können jedoch unterschiedliche Breiten haben.
- Wenn das Raster vertikal angeordnet ist, versucht
StaggeredGridLayoutManager
ist ähnlich wieGridLayoutManager
, aber es ist nicht erforderlich, dass Elemente in einer Zeile dieselbe Höhe (für vertikale Raster) oder Elemente in derselben Spalte dieselbe Breite (für horizontale Raster) haben. Das Ergebnis ist, dass die Elemente in einer Zeile oder Spalte versetzt zueinander dargestellt werden können.
Sie müssen auch das Layout der einzelnen Elemente gestalten. Sie benötigen dieses Layout, wenn Sie den View-Holder entwerfen, wie im nächsten Abschnitt beschrieben.
Adapter und View-Holder implementieren
Nachdem Sie das Layout festgelegt haben, müssen Sie Adapter
und ViewHolder
implementieren. Diese beiden Klassen definieren gemeinsam, wie Ihre Daten dargestellt werden. ViewHolder
ist ein Wrapper um ein View
, das das Layout für ein einzelnes Element in der Liste enthält. Das Adapter
erstellt bei Bedarf ViewHolder
-Objekte und legt auch die Daten für diese Ansichten fest. Der Prozess, bei dem Ansichten ihren Daten zugeordnet werden, wird als Binden bezeichnet.
Wenn Sie Ihren Adapter definieren, überschreiben Sie drei wichtige Methoden:
onCreateViewHolder()
:RecyclerView
ruft diese Methode immer dann auf, wenn ein neuesViewHolder
erstellt werden muss. Mit der Methode wird dieViewHolder
und die zugehörigeView
erstellt und initialisiert. Die Inhalte der Ansicht werden jedoch nicht ausgefüllt, da dieViewHolder
noch nicht an bestimmte Daten gebunden ist.onBindViewHolder()
:RecyclerView
ruft diese Methode auf, um eineViewHolder
mit Daten zu verknüpfen. Die Methode ruft die entsprechenden Daten ab und verwendet sie, um das Layout des Viewholders auszufüllen. Wenn beispielsweise inRecyclerView
eine Liste mit Namen angezeigt wird, kann die Methode den entsprechenden Namen in der Liste finden und dasTextView
-Widget des Viewholders ausfüllen.getItemCount()
:RecyclerView
ruft diese Methode auf, um die Größe des Datasets abzurufen. In einer Adressbuch-App könnte das beispielsweise die Gesamtzahl der Adressen sein. RecyclerView verwendet diese Methode, um zu ermitteln, wann keine weiteren Elemente mehr angezeigt werden können.
Hier ist ein typisches Beispiel für einen einfachen Adapter mit einem verschachtelten ViewHolder
, in dem eine Liste von Daten angezeigt wird. In diesem Fall wird im RecyclerView eine einfache Liste mit Textelementen angezeigt. Dem Adapter wird ein Array von Strings mit dem Text für die ViewHolder
-Elemente übergeben.
Kotlin
class CustomAdapter(private val dataSet: Array<String>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() { /** * Provide a reference to the type of views that you are using * (custom ViewHolder) */ class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val textView: TextView init { // Define click listener for the ViewHolder's View textView = view.findViewById(R.id.textView) } } // Create new views (invoked by the layout manager) override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder { // Create a new view, which defines the UI of the list item val view = LayoutInflater.from(viewGroup.context) .inflate(R.layout.text_row_item, viewGroup, false) return ViewHolder(view) } // Replace the contents of a view (invoked by the layout manager) override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { // Get element from your dataset at this position and replace the // contents of the view with that element viewHolder.textView.text = dataSet[position] } // Return the size of your dataset (invoked by the layout manager) override fun getItemCount() = dataSet.size }
Java
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> { private String[] localDataSet; /** * Provide a reference to the type of views that you are using * (custom ViewHolder) */ public static class ViewHolder extends RecyclerView.ViewHolder { private final TextView textView; public ViewHolder(View view) { super(view); // Define click listener for the ViewHolder's View textView = (TextView) view.findViewById(R.id.textView); } public TextView getTextView() { return textView; } } /** * Initialize the dataset of the Adapter * * @param dataSet String[] containing the data to populate views to be used * by RecyclerView */ public CustomAdapter(String[] dataSet) { localDataSet = dataSet; } // Create new views (invoked by the layout manager) @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { // Create a new view, which defines the UI of the list item View view = LayoutInflater.from(viewGroup.getContext()) .inflate(R.layout.text_row_item, viewGroup, false); return new ViewHolder(view); } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder viewHolder, final int position) { // Get element from your dataset at this position and replace the // contents of the view with that element viewHolder.getTextView().setText(localDataSet[position]); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return localDataSet.length; } }
Das Layout für die einzelnen Ansichtselemente wird wie gewohnt in einer XML-Layoutdatei definiert.
In diesem Fall hat die App eine text_row_item.xml
-Datei wie diese:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/list_item_height"
android:layout_marginLeft="@dimen/margin_medium"
android:layout_marginRight="@dimen/margin_medium"
android:gravity="center_vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/element_text"/>
</FrameLayout>
Nächste Schritte
Das folgende Code-Snippet zeigt, wie Sie RecyclerView
verwenden können.
Kotlin
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val dataset = arrayOf("January", "February", "March") val customAdapter = CustomAdapter(dataset) val recyclerView: RecyclerView = findViewById(R.id.recycler_view) recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.adapter = customAdapter } }
Java
RecyclerView recyclerView = findViewById(R.id.recycler_view); recyclerView.layoutManager = new LinearLayoutManager(this) recyclerView.setAdapter(customAdapter);
Die Bibliothek bietet auch viele Möglichkeiten, Ihre Implementierung anzupassen. Weitere Informationen finden Sie unter Erweiterte Anpassung von RecyclerView.
Randlose Anzeige aktivieren
So aktivieren Sie die randlose Anzeige für ein RecyclerView
:
- Richten Sie ein abwärtskompatibles randloses Display ein, indem Sie
enableEdgeToEdge()
aufrufen. - Wenn sich die Listenelemente anfangs mit den Systemleisten überschneiden, wenden Sie Insets auf
RecyclerView
an. Dazu können Sieandroid:fitsSystemWindows
auftrue
setzen oderViewCompat.setOnApplyWindowInsetsListener
verwenden. - Wenn Sie zulassen möchten, dass die Listenelemente beim Scrollen unter den Systemleisten gezeichnet werden, legen Sie für
android:clipToPadding
den Wertfalse
fürRecyclerView
fest.
Im folgenden Video sehen Sie ein RecyclerView
mit deaktivierter (links) und aktivierter (rechts) Edge-to-Edge-Anzeige:
Beispiel für Inset-Code:
Kotlin
ViewCompat.setOnApplyWindowInsetsListener( findViewById(R.id.my_recycler_view) ) { v, insets -> val innerPadding = insets.getInsets( WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() // If using EditText, also add // "or WindowInsetsCompat.Type.ime()" to // maintain focus when opening the IME ) v.setPadding( innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom) insets }
Java
ViewCompat.setOnApplyWindowInsetsListener( activity.findViewById(R.id.my_recycler_view), (v, insets) -> { Insets innerPadding = insets.getInsets( WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout() // If using EditText, also add // "| WindowInsetsCompat.Type.ime()" to // maintain focus when opening the IME ); v.setPadding( innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom ); return insets; } );
Die RecyclerView
-XML-Datei:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:clipToPadding="false"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Zusätzliche Ressourcen
Weitere Informationen zum Testen auf Android finden Sie in den folgenden Ressourcen.