Android ListView #
Die Recycler View ist eine Erweiterung der Listview. Deshalb wird in diesem Beitrag die ListView vorgestellt und in einem weiteren dann die RecyclerView. Die beiden Views sind konzeptionell sehr ähnlich, wodurch die RecyclerView dann relativ schnell verständlich wird.
Ausgangspunkt im Beispiel ist eine Activity. Natürlich könnte es auch ein Fragment sein.
Die ListView benötigt ein Objekt, das sie nach einzelnen Zeilen fragen kann. Dieses Objekt wird mit setAdapter(…) der ListView übergeben. Zusammengefasst hat der Adapter somit die Aufgabe, Daten aus einem Array oder einer List
Die ListView muss im Layout der Activity oder des Fragments definiert werden:
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/listView"/>
Wenn mit einfachen Datentypen wie String oder Integer gearbeitet wird, hat das Android Projekt schon einen Adapter vorbereitet, der direkt verwendet werden kann. Ausserdem haben sie schon ein einfaches Zeilen-Layout erstellt, das bei Bedarf auch verwendet werden kann. Das Zeilen-Layout wird verwendet, um ein Element in der Liste darzustellen.
Beispiel mit Strings #
Im untenstehenden Beispiel soll Liste voller String in einer ListView dargestellt werden. Dazu wird zuerst der Context angegeben, dann ein Zeilen-Layout beispielsweise vom Android Projekt und zum Schluss eine Liste mit den Daten.
//this ist die Instanz der Activity ansonsten getActivity() verwenden
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray);
Wenn ein eigenes Zeilen-Layout verwendet werden soll, muss auch noch die TextView angeben werden, in der der String dargestellt werden soll.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.myLayout, R.id.usedTextLabel, myStringArray);
Beispiel mit eigenem Adapter #
Damit der eigene Adapter ein wenig spannender ist, wird untenstehend eine eigene POJO Klasse Module verwendet.
In Zeile 13 wird eine Zeile für die ListView erzeugt. Das Layout-XML wird durch ein Android-Objekt “aufgeblasen” (inflated).
Von Zeile 16 bis 20 werden die verschiedenen Click-Listener gesetzt. Da das Zeilen-Layout eine Checkbox enthält, kann auf deren Clicks registriert werden. Ausserdem wird die Zeile mit Daten aus der Daten-Liste gefüllt.
Zeile 26 ist wichtig, da sonst die Liste leer bleibt.
public class Module {
String code;
boolean checked;
public String getCode() {return code;}
public void toggleChecked() {checked = !checked;}
}
MyAdapter adapter = new MyAdapter(this, R.layout.myLayout, moduleList);
Und die Implementierung des Adapters dazu:
public class MyAdapter extends extends ArrayAdapter<Module> {
private List<Module> data;
public MyCustomAdapter(Context context, int rowLayout, List<Module> moduleList) {
super(context, rowLayout, moduleList);
data = moduleList;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
// Alternative: LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
LayoutInflater layoutInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.rowlayout, null);
}
final Module module = data.get(position);
TextView tw = (TextView) convertView.findViewById(R.id.textView);
CheckBox cb = (CheckBox) convertView.findViewById(R.id.checkBox);
cb.setOnClickListener((View v) -> module.toggleChecked());
tw.setText("(" + module.getCode() + ")");
return convertView;
}
@Override
public int getCount() {return data.size();}
}
Verwendung #
Die Verwendung ist in allen Fällen gleich.
Im Lambda auf Zeile 2 gibt der Click-Listener die ListView in der Variable parent zurück. Die Variable view enthält eine View, die in der Funktion getView(…) erzeugt wurde. Die position entspricht dem Index der Daten in der Datenliste. Zum Schluss noch eine id Variable, dass mit getItemId(…) angepasst hätte werden können.
Der Click-Listener wird aufgerufen, sobald der User auf ein Item klickt. Dabei muss der User z.B. nicht auf die Checkbox drücken sondern es reicht, dass auf die betreffende Zeile geklickt wurde.
listView.setAdapter(adapter);
listView.setOnItemClickListener((parent, view, position, id) -> {
Module module = (Module) parent.getItemAtPosition(position);
module.setSelected(!module.isSelected());
dataAdapter.notifyDataSetChanged();
});