Kürzlich habe ich eine Leserzuschrift zu meinem Kotlin-Buch erhalten: »Wie realisiert man eine Mehrfachauswahl in einer Liste innerhalb einer Android-App?«. Konkret bezog sich die Frage auf die RecyclerView
, die ich im Abschnitt 23.7 »Listen und Tabellen« recht ausführlich behandle.
In meiner Antwort beziehe ich mich auf das im Buch präsentierte Beispielprogramm, das in einer RecyclerView
die die deutschen Bundesländer inklusive einiger Eckdaten anzeigt.
Datenmodell
Die erste Voraussetzung für eine Mehrfachauswahl besteht darin, dass es einen Ort gibt, wo Sie sich die Auswahl merken. In meinem Beispielprogramm ist die Datenquelle einfach ein Array von Country
-Objekten. Also habe ich dieser Klasse eine zusätzliche Eigenschaft isSelected
hinzugefügt:
class Country(val name: String,
val area: Double,
val population: Int,
val capital: String,
var isSelected: Boolean = false) // <- neu!
{
// Code unverändert ...
}
RecyclerView-Adapter
Im RecyclerView-Adapter ist die Methode onBindViewHolder
für die grafische Darstellung der Listenelemente zuständig. Hier müssen Sie Code einbauen, um ausgewählte Einträge optisch hervorzuheben. Ich habe mich dazu entschieden, einfach die Hintergrundfarbe grau statt weiß darzustellen — aber es gibt natürlich viele andere Optionen.
class CountryAdapter(private val countries: List<Country>,
private val context: Context)
: RecyclerView.Adapter<CountryVH>()
{
...
override fun onBindViewHolder(holder: CountryVH,
pos: Int)
{
holder.txtCountry.text = countries[pos].name
// ... usw.
// neuer Code: Hintergrundfarbe je nach Auswahl
if (countries[pos].isSelected)
holder.itemView.setBackgroundColor(Color.LTGRAY)
else
holder.itemView.setBackgroundColor(Color.WHITE)
...
}
}
Reaktion auf das On-Click-Ereignis
Ebenfalls in onBindViewHolder
wird ein Lambda-Ausdruck übergeben, der immer dann ausgeführt wird, wenn der Benutzer der App einen Eintrag der Liste berührt, um diesen auszuwählen bzw. um die Auswahl wieder aufzuheben. Dort sind zwei Dinge wichtig: Zum Einen wird die isSelected
-Eigenschaft des Array-Elements der Datenquelle geändert. Und zum Anderen wird für die gesamte RecyclerView
mit notifyDataSetChanged
neu gezeichnet. (Andernfalls würde die Statusänderung nicht sofort sichtbar.)
class CountryAdapter(private val countries: List<Country>,
private val context: Context)
: RecyclerView.Adapter<CountryVH>()
{
...
override fun onBindViewHolder(holder: CountryVH,
pos: Int)
{
...
// Reaktion auf Auswahl des Listeneintrags
holder.itemView.setOnClickListener {
// aktuelle Auswahl invertieren
countries[pos].isSelected = !countries[pos].isSelected
// ganze Liste neu zeichnen
this.notifyDataSetChanged()
}
}
}
Beispielcode
Den gesamten Beispielcode finden Sie hier zum Download:
https://kofler.info/uploads/kotlin/kap23-recycler-multiselect.zip
Bitte beachten Sie, dass das Beispiel im Vergleich zu den Listings im Buch auf die neue ViewBinding-Technik umgebaut wurde (siehe auch Kotlin-Updates: Android Studio 4.2).