ListView ist eine grundlegende Android-Komponente zur Anzeige vertikaler Listen, verfügbar ab API 1 (Android 1.0). ListView erstellt mithilfe von ArrayAdapter eine Liste von Elementen und unterstützt benutzerdefinierte Zellenlayouts. Lassen Sie uns herausfinden, was ListView ist, wie man es konfiguriert und welche Fallstricke diese alte, aber immer noch verwendete Komponente verbirgt. Bei IT Sectr begegnen wir ListView in Legacy-Projekten und wahren Abwärtskompatibilität mit Android 4.4. Zum Vergleich mit der modernen Alternative lesen Sie den Artikel über RecyclerView.
Wichtige Erkenntnisse
ListView ist eine ViewGroup aus dem Paket android.widget, die zur Anzeige einer scrollbaren Liste von Elementen entwickelt wurde. ListView implementiert das AdapterView-Muster: Daten werden über einen Adapter (Adapter) übergeben, der Datenelemente in auf dem Bildschirm angezeigte Views umwandelt. ListView existiert seit der ersten Version (API 1) im Android SDK und benötigt keine zusätzlichen Bibliotheken.
Die Architektur von ListView ist einfacher als die von RecyclerView: LayoutManager ist integriert (nur vertikales Scrollen), Änderungsanimationen fehlen, Trennlinien werden über das XML-Attribut android:divider gesetzt. ListView fügt automatisch OverScrollView und Fokus-Hervorhebung hinzu, was das Prototyping vereinfacht. Laut Statista (2025) enthalten etwa 15% der Top-100-Android-Apps im Play Store noch ListView — meist Legacy-Projekte mit minimalem Support.
ListView war von 2008 bis 2014 die primäre Listenkomponente in Android, bis RecyclerView auf der Google I/O 2014 vorgestellt wurde. Trotz des teilweisen Veraltetseins (soft-deprecated) bleibt ListView in allen Android-Versionen verfügbar und ist in SDK API 35 nicht als @Deprecated markiert. Wenn Ihr Projekt Android 4.4 (API 19) und niedriger unterstützt, ist ListView die einzige integrierte Wahl, da RecyclerView AndroidX und Gradle-Abhängigkeiten erfordert.
ArrayAdapter ist der beliebteste Adapter für ListView. Er nimmt eine List<T> und ein Layout für jedes Element. Standardmäßig ruft ArrayAdapter toString() für jedes Objekt auf und zeigt den Text in simple_list_item_1 (einem einzelnen TextView) an. Für eine benutzerdefinierte Anzeige müssen Sie getView() überschreiben oder ein benutzerdefiniertes Layout an den Konstruktor übergeben.
// ListView mit ArrayAdapter (einfacher Text)
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val countries = listOf(
"Russland", "USA", "Deutschland",
"Frankreich", "Japan", "China", "Brasilien"
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val adapter = ArrayAdapter<String>(
this,
android.R.layout.simple_list_item_1,
countries
)
binding.listView.adapter = adapter
// Klickbehandlung
binding.listView.onItemClickListener =
AdapterView.OnItemClickListener { _, _, position, _ ->
Toast.makeText(this, countries[position], Toast.LENGTH_SHORT).show()
}
}
}
SimpleAdapter ist für Listen aus Map-Daten konzipiert. Er nimmt eine List<Map<String, Any>> und ein from/to-Array zum Binden von Map-Schlüsseln an Widget-IDs im Layout. SimpleAdapter ist praktisch für schnelle Prototypen, wenn keine separate Adapterklasse benötigt wird. Der Nachteil ist das Fehlen von typsicherer Typisierung und die Komplexität bei benutzerdefinierter Logik.
<!-- ListView-Layout -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@color/divider"
android:dividerHeight="1px"
android:scrollbars="vertical" />
</LinearLayout>
Der benutzerdefinierte Adapter für ListView überschreibt die Methode getView(), die RecyclerView in onCreateViewHolder + onBindViewHolder aufteilt. In ListView sind beide Schritte kombiniert, daher muss der Entwickler das ViewHolder-Muster eigenständig über convertView (wiederverwendbare View) und die setTag()-Methode implementieren.
// Datenmodell
data class Product(
name: String,
price: String,
imageResId: Int
)
// Benutzerdefinierter Adapter mit ViewHolder
class ProductAdapter(
context: Context,
private val products: List<Product>
) : ArrayAdapter<Product>(context, 0, products) {
// ViewHolder für Caching
private class ViewHolder(view: View) {
val nameText: TextView = view.findViewById(R.id.tvName)
val priceText: TextView = view.findViewById(R.id.tvPrice)
val imageView: ImageView = view.findViewById(R.id.ivProduct)
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: LayoutInflater.from(context)
.inflate(R.layout.item_product, parent, false)
.also { it.tag = ViewHolder(it) }
val holder = view.tag as ViewHolder
val product = getItem(position)
holder.nameText.text = product.name
holder.priceText.text = product.price
holder.imageView.setImageResource(product.imageResId)
return view
}
}
Hauptunterschied zu RecyclerView: In ListView wird die Methode getView() jedes Mal aufgerufen, wenn ein Element auf dem Bildschirm erscheint. Wenn convertView und ViewHolder nicht verwendet werden, erzeugt jeder Scrollvorgang ein neues View-Objekt, was zu Speicherlecks und Verzögerungen bei Listen mit mehr als 50 Elementen führt. ViewHolder mit view.tag ist eine obligatorische Optimierung für ListView mit benutzerdefinierten Layouts.
ListView hat vier architektonische Einschränkungen, die Google in RecyclerView behoben hat: (1) nur vertikale Ausrichtung — keine Gitter, horizontalen Listen oder Kaskaden; (2) keine granularen Benachrichtigungen — jede Datenänderung löst eine vollständige Neuzeichnung über notifyDataSetChanged() aus, was zu Ruckeln führt; (3) keine integrierte Animation zum Hinzufügen/Entfernen von Elementen; (4) keine Trennung der Zuständigkeiten — LayoutManager ist integriert, ItemAnimator fehlt.
<!-- item_product.xml — ListView-Element-Layout -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="12dp">
<ImageView
android:id="@+id/ivProduct"
android:layout_width="56dp"
android:layout_height="56dp"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingStart="12dp">
<TextView
android:id="@+id/tvName"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvPrice"
android:textSize="14sp"
android:textColor="@color/price" />
</LinearLayout>
</LinearLayout>
Praktische Auswirkungen: Bei Listen mit bis zu 20 Elementen arbeitet ListView genauso schnell wie RecyclerView. Ab 100+ Elementen wird der Unterschied spürbar: ListView beginnt FPS einzubüßen, da Diff-Berechnungen und erzwungener ViewHolder fehlen. Für Listen mit häufigen Aktualisierungen (Chat, Feed, Logs) ist ListView nicht geeignet — verwenden Sie RecyclerView mit Paging 3. Bei IT Sectr migrieren wir ListView zu RecyclerView, sobald wir an Legacy-Bildschirmen mit mehr als 50 Elementen arbeiten.
ListView bietet eine Reihe von XML-Attributen zur schnellen Konfiguration ohne Code: android:divider (Farbe/Drawable des Trennzeichens), android:dividerHeight (Dicke), android:scrollbars (Bildlaufleisten), android:fastScrollEnabled (Schnellscrollen per Handler), android:choiceMode (Auswahlmodus: singleChoice, multipleChoice). Das Attribut android:entries ermöglicht das Befüllen der Liste aus einem Ressourcen-Array (string-array) ohne Adapter.
| Attribut | Beschreibung | Beispielwert |
|---|---|---|
| android:divider | Farbe oder Drawable des Trennzeichens | @color/gray_light |
| android:dividerHeight | Dicke des Trennzeichens in px/dp | 1dp |
| android:entries | String-Array aus Ressourcen | @array/countries |
| android:choiceMode | Element-Auswahlmodus | singleChoice |
| android:fastScrollEnabled | Schnellscrollen | true |
| android:overlapAnchor | Anker für Popup-Listen (API 21+) | true |
Auswahlmodus: choiceMode="singleChoice" aktiviert den RadioButton-Stil, bei dem das ausgewählte Element hervorgehoben wird. choiceMode="multipleChoice" — Kontrollkästchen für mehrere Elemente. Auswahldaten sind über listView.checkedItemPosition oder listView.checkedItemIds verfügbar. Wichtig: Bei choiceMode verwendet ListView StateListDrawable für den Hintergrund — setzen Sie Ihren eigenen Selektor, wenn das Standardblau nicht zum Design passt.
Die Wahl zwischen ListView und RecyclerView hängt von den Projektanforderungen ab. RecyclerView ist der moderne Standard, aber ListView kann für einfache Bildschirme mit minimalen Wartungskosten für Legacy-Code gerechtfertigt sein. Vergleich aller wichtigen Parameter:
| Parameter | ListView | RecyclerView |
|---|---|---|
| Bibliotheksgröße | Im SDK integriert (≈60 KB) | AndroidX (≈300 KB mit Abhängigkeiten) |
| Mindestversion | API 1 | API 14 (über AndroidX) |
| Ausrichtung | Nur vertikal | Vertikal, horizontal, Gitter, gestaffelt |
| ViewHolder | Manuelle Implementierung | Architekturbedingt erforderlich |
| Animation | Nur Überblendungen | DefaultItemAnimator (add, remove, move, change) |
| Granulare Updates | Nein (nur notifyDataSetChanged) | notifyItemInserted/Removed/Changed |
| Klick-Listener | onItemClickListener (integriert) | Über ViewHolder (nicht integriert) |
| Leistung | Ausreichend für Listen bis 50 Elemente | Stabile 60 FPS für 1000+ Elemente |
Fazit: Für neue Projekte verwenden Sie RecyclerView. Lassen Sie ListView nur in Legacy-Code, wo die Migration unverhältnismäßig teuer ist. Laut den Material Design 3-Richtlinien (2026) sollten Listen jeder Komplexität RecyclerView verwenden, um moderne Leistungs- und Zugänglichkeitsstandards zu erfüllen.
Häufig gestellte Fragen
ListView ist in Android SDK API 35 nicht als @Deprecated markiert, aber Google empfiehlt die Verwendung in neuen Projekten nicht (soft-deprecated). Die Komponente bleibt in allen Android-Versionen funktionsfähig. RecyclerView ist seit 2014 der offizielle Ersatz. Wenn Sie ein neues Projekt starten — wählen Sie RecyclerView. Wenn Sie ein bestehendes Projekt warten — ListView funktioniert weiterhin ohne Änderungen.
ListView unterstützt die Methoden addHeaderView(View, Object, boolean) und addFooterView(View, Object, boolean). Header und Footer werden zur allgemeinen Elementliste hinzugefügt, nehmen aber nicht am Adapter teil — sie werden immer am Anfang und Ende der Liste angezeigt. Wichtig: Fügen Sie Header/Footer hinzu, bevor Sie den Adapter setzen (setAdapter()), sonst werden sie nicht berücksichtigt. Nach dem Hinzufügen eines Headers verschieben sich die Positions-IDs der Elemente um die Anzahl der Header.
Sowohl ListView als auch ScrollView verarbeiten vertikale Gesten, was zu einem Konflikt führt: Die äußere ScrollView fängt das Scrollen ab, und ListView scrollt nicht. Lösungen: (1) Verschachteln Sie ListView nicht in ScrollView — verwenden Sie RecyclerView mit NestedScrollingChild, (2) ersetzen Sie ScrollView durch NestedScrollView (API 21+), (3) verwenden Sie ListView mit fester Höhe (android:layout_height="...dp") innerhalb von ScrollView, aber dies beeinträchtigt die Anpassungsfähigkeit.
Das Löschen von Daten in ListView hängt vom Adaptertyp ab. Für ArrayAdapter: adapter.clear() und adapter.addAll(newList) gefolgt von adapter.notifyDataSetChanged(). Für benutzerdefinierten Adapter: Aktualisieren Sie die Datenliste und rufen Sie notifyDataSetChanged() auf. Hinweis: listView.invalidateViews() zeichnet nur Views neu, aktualisiert aber keine Daten. Ändern Sie Daten immer über den Adapter, nicht direkt.
Die Höhe eines ListView-Elements wird im Element-Layout festgelegt. Wenn das Layout layout_height="wrap_content" verwendet, passt sich die Höhe dem Inhalt an. Für eine feste Höhe aller Elemente verwenden Sie einen benutzerdefinierten Adapter, der LayoutParams in getView() setzt: view.layoutParams.height = resources.getDimensionPixelSize(R.dimen.itemHeight). Für unterschiedliche Höhen verwenden Sie RecyclerView mit verschiedenen View-Typen.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch