Rozwijalna lista wielokrotnego wyboru
Ten temat jest kontynuacją poprzedniego tematu dotyczącego kontrolki ListView (zobacz). Kontrolka ListView ma trzy tryby pracy. O trybie pracy kontrolki decyduje parametr ChoiceMode.
Parametr choiceMode może przyjąć jedną z poniższych wartości:
- CHOICE_MODE_NONE ? brak możliwości zaznaczenia danej opcji (opcja domyślna)
- CHOICE_MODE_SINGLE ? można zaznaczyć tylko jedną opcję
- CHOICE_MODE_MULTIPLE ? można zaznaczyć kilka opcji
Lista rozwijalna standardowo pracuje bez możliwości wyboru elementu listy. Ustawienie parametru trybu pracy wykonuje się metodą setChoiceMode. Przykład użycia
Wskazówka:
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
Pracując z listą w układzie wyboru należy przygotować dwa adaptery. Jeden adapter służy do wczytania wszystkich elementów listy. Drugi adapter wczytuje wybrane elementy listy.
Przygotowanie widoku (layout)
Główny widok aplikacji ma pracować jako LinearLayout w układzie pionowym, który będzie zawierać kontrolkę ListView i dwie kontrolki Button
Zawartość pliku activity_main.xml
Wskazówka:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="520dp"
android:divider="#D9F3BC"
android:dividerHeight="2dp"/>
<Button
android:id="@+id/button1"
android:layout_width="143dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Ładuj listę" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Pokaż wybrane" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Zasoby kontroli ListView
Zasoby tworzące zawartość kontrolki ListView zapiszemy w pliku XML (res/ values /strings.xml) jako tablicę łańcuchów znaków (string-array)
Wskazówka:
<resources>
<string name="app_name">Lista widoku wielokrotnego wyboru</string>
<!--tablica krajów UE-->
<string-array name="KrajeUE">
<item>Austria</item>
<item>Włochy</item>
<item>Węgry</item>
<item>Szwecja</item>
<item>Słowenia</item>
<item>Słowacja</item>
<item>Rumunia</item>
<item>Portugalia</item>
<item>Polska</item>
<item>Belgia</item>
<item>Bułgaria</item>
<item>Chorwacja</item>
<item>Cypr</item>
<item>Czechy</item>
<item>Dania</item>
<item>Estonia</item>
<item>Finlandia</item>
<item>Francja</item>
<item>Grecja</item>
<item>Hiszpania</item>
<item>Holandia</item>
<item>Irlandia</item>
<item>Litwa</item>
<item>Luksemburg</item>
<item>Łotwa</item>
<item>Malta</item>
<item>Niemcy</item>
</string-array>
</resources>
Funkcja wczytująca elementy listy
Wczytanie elementów listy oprzemy na przygotowaniu własnej funkcji, której ciało wykona poniższe bloki czynności
- odczytaj tablice zasobów z pliku XML
- przygotuj adapter listy
- ustaw tryb pracy listy (wielokrotny wybór)
- załaduj adapter do listy
Dodatkowo możemy przygotować nagłówek i stopkę dla kontrolki ListView
Wskazówka:
fun LadujListe(){
val tabKraje=resources.getStringArray(R.array.KrajeUE)
tabKraje.sort()
//w adaptzerz ustaw typ listy wielokrotnego wyboru
val moj_adapter=ArrayAdapter<String>(this,
android.R.layout.simple_list_item_checked,
tabKraje)
val listView=findViewById<ListView>(R.id.listView)
//ustawa tryb wielokrotnego wtboru
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE)
//załaduj adapter wczytanych elementów
listView.adapter=moj_adapter
Naglowek(listView,"Kraje UE", "#FF94EF8E")
Stopka(listView,"Lista zawiera "
+tabKraje.count().toString()
+" elementów","#FF94EF8E")
}
Funkcja tworząca nagłówek i stopkę
Wskazówka:
fun Naglowek(listView: ListView, tytul:String, kolor:String){
val staryNaglowek=listView.findViewById<TextView>(idNaglowek)
if(staryNaglowek!=null)listView.removeHeaderView(staryNaglowek)
val naglowek= TextView(this)
naglowek.setTextSize(22f)
naglowek.setText(tytul)
naglowek.setBackgroundColor(Color.parseColor(kolor))
naglowek.id=idNaglowek
listView.addHeaderView(naglowek)
}
fun Stopka(listView: ListView, tytul:String, kolor:String){
val staraStopka=listView.findViewById<TextView>(idStopka)
if(staraStopka!=null)listView.removeFooterView(staraStopka)
val stopka= TextView(this)
stopka.setTextSize(14f)
stopka.setText(tytul)
stopka.setBackgroundColor(Color.parseColor(kolor))
stopka.id=idStopka
listView.addFooterView(stopka)
}
Do projektu dodamy dynamiczne identyfikatory nagłówka i stopki
Wskazówka:
class MainActivity : AppCompatActivity() {
val idNaglowek= View.generateViewId()
val idStopka= View.generateViewId()
Załadowanie elementów listy wykonamy przez kliknięcie w kontrolkę Button
Wskazówka:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bt1=findViewById<Button>(R.id.button1)
bt1.setOnClickListener{ LadujListe() }
}
Skompiluj projekt i sprawdź działanie aplikacji.
Po załadowaniu elementów listy zauważysz ikony wyboru elementów listy.
Obsługa wybranych elementów
Obsługa wybranego elementu lub wybranych elementów listy polega na odczytaniu stanu wyboru. Dla kontrolki ListView stan wyboru zwraca metoda isItemChecked(). W tym projekcje utworzymy dodatkowy adapter, który z wybranych elementów listy zrobi nową listę. Nowa lista zostanie ponownie wczytana do kontrolki ListView jako elementy wybrane.
Wskazówka:
fun PokazWybrane(){
//deklaracja pustej tablicy stringów
var tabWybrane=emptyArray<String>()
val listView=findViewById<ListView>(R.id.listView)
for(i in 0..listView.count){
if(listView.isItemChecked(i))
tabWybrane+= listView.getItemAtPosition(i).toString()
}
//adapter prostej listy
val moj_adapter=ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
tabWybrane)
listView.adapter=moj_adapter
Naglowek(listView,"Wybrane kraje UE", "#FF94EF8E")
Stopka(listView,"Lista zawiera "
+tabWybrane.count().toString()
+" elementów","#FF94EF8E")
}
Obsługę wybranych elementów zrealizujemy w kliknięciu drugiej kontrolki Button
Wskazówka:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bt1=findViewById<Button>(R.id.button1)
bt1.setOnClickListener{ LadujListe() }
val bt2=findViewById<Button>(R.id.button2)
bt2.setOnClickListener{ PokazWybrane() }
}
Skompiluj program i sprawdź działanie.
Pełny kod pliku MainActivity.kt
Wskazówka:
import android.graphics.Color
import android.os.Bundle
import android.view.View
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.ListView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
val idNaglowek= View.generateViewId()
val idStopka= View.generateViewId()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bt1=findViewById<Button>(R.id.button1)
bt1.setOnClickListener{ LadujListe() }
val bt2=findViewById<Button>(R.id.button2)
bt2.setOnClickListener{ PokazWybrane() }
}
fun Naglowek(listView: ListView, tytul:String, kolor:String){
val staryNaglowek=listView.findViewById<TextView>(idNaglowek)
if(staryNaglowek!=null)listView.removeHeaderView(staryNaglowek)
val naglowek= TextView(this)
naglowek.setTextSize(22f)
naglowek.setText(tytul)
naglowek.setBackgroundColor(Color.parseColor(kolor))
naglowek.id=idNaglowek
listView.addHeaderView(naglowek)
}
fun Stopka(listView: ListView, tytul:String, kolor:String){
val staraStopka=listView.findViewById<TextView>(idStopka)
if(staraStopka!=null)listView.removeFooterView(staraStopka)
val stopka= TextView(this)
stopka.setTextSize(14f)
stopka.setText(tytul)
stopka.setBackgroundColor(Color.parseColor(kolor))
stopka.id=idStopka
listView.addFooterView(stopka)
}
fun LadujListe(){
val tabKraje=resources.getStringArray(R.array.KrajeUE)
tabKraje.sort()
//w adaptzerz ustaw typ listy wielokrotnego wyboru
val moj_adapter=ArrayAdapter<String>(this,
android.R.layout.simple_list_item_checked,
tabKraje)
val listView=findViewById<ListView>(R.id.listView)
//ustawa tryb wielokrotnego wtboru
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE)
//załaduj adapter wczytanych elementów
listView.adapter=moj_adapter
Naglowek(listView,"Kraje UE", "#FF94EF8E")
Stopka(listView,"Lista zawiera "+
tabKraje.count().toString()+
" elementów","#FF94EF8E")
}
fun PokazWybrane(){
//deklaracja pustej tablicy stringów
var tabWybrane=emptyArray<String>()
val listView=findViewById<ListView>(R.id.listView)
for(i in 0..listView.count){
if(listView.isItemChecked(i))
tabWybrane+= listView.getItemAtPosition(i).toString()
}
//adapter prostej listy
val moj_adapter=ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
tabWybrane)
listView.adapter=moj_adapter
Naglowek(listView,"Wybrane kraje UE", "#FF94EF8E")
Stopka(listView,"Lista zawiera "+
tabWybrane.count().toString()+
" elementów","#FF94EF8E")
}
}