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 jedes Element aussieht. Die RecyclerView-Bibliothek erstellt die Elemente dann dynamisch, wenn sie benötigt werden.
Wie der Name schon sagt, werden diese einzelnen Elemente von RecyclerView recycelt. Wenn ein Element vom Bildschirm gescrollt wird, wird die Ansicht nicht von RecyclerView gelöscht. Stattdessen verwendet RecyclerView die Ansicht für neue Elemente, die auf dem Bildschirm angezeigt werden, wieder. RecyclerView verbessert die Leistung und die Reaktionsfähigkeit Ihrer App und reduziert den Stromverbrauch.
Schlüsselklassen
Mehrere Klassen arbeiten zusammen, um Ihre dynamische Liste zu erstellen.
RecyclerViewist dasViewGroup, das die Ansichten für Ihre Daten enthält. Es ist selbst eine Ansicht, sodass SieRecyclerViewIhrem Layout wie jedes andere UI-Element hinzufügen können.Jedes einzelne Element in der Liste wird durch ein ViewHolder-Objekt definiert. Wenn der ViewHolder erstellt wird, sind ihm keine Daten zugeordnet. Nachdem der View Holder erstellt wurde, wird er vom
RecyclerViewan seine Daten gebunden. Sie definieren den ViewHolder, indem SieRecyclerView.ViewHoldererweitern.RecyclerViewfordert Ansichten an und bindet sie an ihre Daten, indem Methoden im Adapter aufgerufen werden. Sie definieren den Adapter, indem SieRecyclerView.Adaptererweitern.Der Layoutmanager ordnet die einzelnen Elemente in Ihrer Liste an. Du kannst einen der Layoutmanager aus der RecyclerView-Bibliothek verwenden oder einen eigenen definieren. Layoutmanager basieren alle auf der abstrakten Klasse
LayoutManagerder Bibliothek.
In der RecyclerView-Beispiel-App (Kotlin) oder der RecyclerView-Beispiel-App (Java) sehen Sie, wie alle Teile zusammenpassen.
Schritte zur Implementierung 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-Layoutmanager der RecyclerView-Bibliothek verwenden.
Legen Sie fest, wie die einzelnen Elemente in der Liste aussehen und sich verhalten sollen. Erweitern Sie die Klasse
ViewHolderbasierend auf diesem Design. Ihre Version vonViewHolderbietet alle Funktionen für Ihre Listenelemente. Der ViewHolder ist ein Wrapper um eineView, die vonRecyclerViewverwaltet wird.Definieren Sie die
Adapter, die Ihre Daten mit denViewHolder-Ansichten verknüpft.
Es gibt auch erweiterte Anpassungsoptionen, mit denen Sie Ihre 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 gängigsten Layoutsituationen abdecken:
LinearLayoutManagerordnet die Elemente in einer eindimensionalen Liste an.GridLayoutManagerordnet die Elemente in einem zweidimensionalen Raster an:- Wenn das Raster vertikal angeordnet ist, versucht
GridLayoutManager, alle Elemente in jeder Zeile mit derselben Breite und Höhe zu versehen. Verschiedene Zeilen können jedoch unterschiedliche Höhen haben. - Wenn das Raster horizontal angeordnet ist, versucht
GridLayoutManager, alle Elemente in jeder Spalte mit derselben Breite und Höhe zu versehen. Verschiedene Spalten können jedoch unterschiedliche Breiten haben.
- Wenn das Raster vertikal angeordnet ist, versucht
StaggeredGridLayoutManagerähneltGridLayoutManager, erfordert jedoch nicht, 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 führt dazu, dass die Elemente in einer Zeile oder Spalte versetzt zueinander angeordnet werden.
Außerdem müssen Sie das Layout der einzelnen Elemente entwerfen. Sie benötigen dieses Layout, wenn Sie den ViewHolder 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 arbeiten zusammen, um zu definieren, wie Ihre Daten angezeigt werden. ViewHolder ist ein Wrapper um ein View, das das Layout für ein einzelnes Element in der Liste enthält. Adapter erstellt nach Bedarf ViewHolder-Objekte und legt auch die Daten für diese Ansichten fest. Der Prozess, bei dem Ansichten mit ihren Daten verknüpft werden, wird als Bindung bezeichnet.
Wenn Sie Ihren Adapter definieren, überschreiben Sie drei wichtige Methoden:
onCreateViewHolder():RecyclerViewruft diese Methode auf, wenn ein neuesViewHoldererstellt werden muss. Die Methode erstellt und initialisiert denViewHolderund die zugehörigeView, füllt aber nicht den Inhalt der Ansicht aus. DerViewHolderwurde noch nicht an bestimmte Daten gebunden.onBindViewHolder():RecyclerViewruft diese Methode auf, um einenViewHoldermit Daten zu verknüpfen. Die Methode ruft die entsprechenden Daten ab und verwendet sie, um das Layout des ViewHolders zu füllen. Wenn derRecyclerViewbeispielsweise eine Liste mit Namen anzeigt, kann die Methode den entsprechenden Namen in der Liste finden und dasTextView-Widget des ViewHolders ausfüllen.getItemCount():RecyclerViewruft diese Methode auf, um die Größe des Datasets abzurufen. In einer Adressbuch-App könnte dies beispielsweise die Gesamtzahl der Adressen sein. RecyclerView verwendet diese Methode, um zu ermitteln, wann keine Elemente mehr angezeigt werden können.
Hier ist ein typisches Beispiel für einen einfachen Adapter mit einer verschachtelten ViewHolder, die eine Liste von Daten anzeigt. In diesem Fall zeigt die RecyclerView eine einfache Liste von Textelementen an. An den Adapter wird ein Array von Strings übergeben, die den Text für die ViewHolder-Elemente enthalten.
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 außerdem viele Möglichkeiten, die Implementierung anzupassen. Weitere Informationen finden Sie unter Erweiterte RecyclerView-Anpassung.
Randlose Anzeige aktivieren
So aktivierst du die randlose Anzeige für ein RecyclerView:
- Richten Sie eine abwärtskompatible randlose Anzeige ein, indem Sie
enableEdgeToEdge()aufrufen. - Wenn die Listenelemente die Systemleisten anfangs überlappen, wenden Sie Insets auf das
RecyclerViewan. Dazu können Sieandroid:fitsSystemWindowsauftruesetzen oderViewCompat.setOnApplyWindowInsetsListenerverwenden. - Erlaube, dass die Listenelemente beim Scrollen unter den Systemleisten gezeichnet werden, indem du
android:clipToPaddingfürRecyclerViewauffalsesetzt.
Das folgende Video zeigt ein RecyclerView mit deaktiviertem (links) und aktiviertem (rechts) Edge-to-Edge-Display:
Beispielcode für Inset:
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:
<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 unter Android finden Sie in den folgenden Ressourcen.