Android-Programmierung Listen

Willemers Informatik-Ecke

Das einzig seriöse Javabuch :-) Mehr...

.. enthält ein Kapitel zur Android-Programmierung.
Bei Amazon bestellen
2016-04-19
Auf diesen Seiten halte ich meine Erfahrungen im Bereich der Android-Programmierung fest, um sie später nachschlagen zu können. Die Ausführungen sind kein vollständiger Kurs, manchmal nur Notizen, aber vielleicht anderen hilfreich.

Eine ListActivity mit einer einspaltigen Liste

Die erste Liste stellt eine Liste von Strings dar. In jeder Zeile gibt es also nur ein Element. Als Quelle der Liste wird ein String-Array verwendet, in denen einfach nur irgendwelche Begriffe abgelegt sind.

Über dieses Array wird ein ArrayAdapter gelegt, der die Elemente mit einem Layout verbindet.

public class GewichtListActivity extends ListActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String[] values = new String[]{"Android", "Uhu", "Super"};
        ArrayAdapter adapter 
              = new ArrayAdapter(this,
                R.layout.listelement_text, R.id.tvListElement, values);
        setListAdapter(adapter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
...
}
Es wird auf eine XML-Datei namens listelement_text.xml unter layout referenziert, in der ein TextView tvListElement definiert ist.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >

    <TextView
        android:id="@+id/tvListElement"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

</RelativeLayout>
Die XML-Datei beschreibt nicht etwa einen kompletten Bildschirm, sondern nur die Zeile einer ListView.

Die Liste zeigt Datenbankfelder

Dieses Mal handelt es sich nicht um eine ListActivity, sondern um eine ganz normale Activity, die ein ListView als Kontrollelement besitzt.
public class GewichtListActivity extends Activity {
    private GewichtDB dbHandler;
    private Cursor dbCursor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gewicht_list);

        dbHandler = new GewichtDB(this);
        dbCursor = dbHandler.query();

        ListView listView = (ListView) findViewById(R.id.lvGewichtList);
        // hier werden die Gewichte zwischengeparkt
        ArrayList gewichte = new ArrayList();
        // Datenbank auslesen
        int spalteGewicht = dbCursor.getColumnIndex(GewichtDB.GEWICHT);
        while (dbCursor.moveToNext()) {
            double gewicht = dbCursor.getDouble(spalteGewicht);
            gewichte.add("" + gewicht);
        }
        ArrayAdapter adapter = new ArrayAdapter(this, 
                R.layout.listelement_text, R.id.tvListElement, gewichte);
        listView.setAdapter(adapter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
Das Layout activity_gewicht_list gestaltet den Bildschirm der Activity und enthält einen TextView als Überschrift und eine ListView, die dann die Daten aufnimmt.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="de.willemer.gewichte.GewichtListActivity">

    <TextView
        android:id="@+id/textView"
        android:text="Die Gewichte"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <ListView android:id="@+id/lvGewichtList" android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_below="@+id/textView"
        />

</RelativeLayout>
Der ArrayAdapter sucht in der Datei listelement_text.xml nach dem Element tvListElement. Diese sieht so aus:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >

    <TextView
        android:id="@+id/tvListElement"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

</RelativeLayout>

Beispiel: ListView für die Spielerliste

In der Activity wird eingetragen, dass es eine ListView geben soll.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".SpielerActivity">
    <ListView
        android:id="@+id/spielerliste"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>
</RelativeLayout>
Im gleichen Verzeichnis res/layout wird eine weitere Datei für das Layout des Listenelements angelegt. layout rechts anklicken, New | Layout ressource file Dateiname (list_item_spieler), Root element (TextView) Damit erhält das Element kein Layout für den Gesamtschirm, sondern das eines Kontrollelements. Dem Textview werden noch folgende Attribute hinzugefügt:
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:id="@+id/list_item_spieler" >

Ereignisbehandlung einer ListView

Das "Anklicken" eines Elements soll zu einer Reaktion des Programms führen. Dazu muss ein OnItemClickListener definiert und dessen Methode onItemClick() implementiert werden. Damit die Liste weiß, dass es einen OnItemClickListener gibt, muss die Methode setOnItemClickListener() aufgerufen werden. Das passiert typischerweise in onCreate() der
Activity und sieht dann so aus:
listView = (ListView) findViewById(R.id.listView1);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView listView, View view, int position, long id) {
        // Holt den Cursor für das selektierte Element der Liste
        Cursor cursor = (Cursor) listView.getItemAtPosition(position);
        editItem(cursor, position);
    }
});
In diesem besonderen Fall zeigt die Liste eine Datenbank und arbeitet darum mit einem Cursor.

Soll längeres Tatschen zu einem Kontextmenü führen, wird der Activity ein Kontextmenü hinterlegt. Dazu werden folgende Schritte benötigt:

registerForContextMenu(listView);
Die Activity reagiert mit einem Kontextmenü beim längeren Drücken auf ein Element der ListView listView.

Das wird irgendwann zur Erzeugung eines Kontextmenüs führen. Dabei wird dann onCreateContextMenu() aufgerufen, die in der Activity definiert wird.

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_voklist, menu);
}
Hier wird die XML-Datei menu_voklist.xml angegeben, die das Kontextmenü beschreibt.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".VokListe">
    <item android:id="@+id/action_lstchg" android:title="@string/action_chg"
        android:orderInCategory="100" app:showAsAction="never" />
    <item android:id="@+id/action_lstdel" android:title="@string/action_del"
        android:orderInCategory="100" app:showAsAction="never" />

</menu>
Nun muss noch auf das Anklicken eines Menüpunktes reagiert werden. Dies erledigt die Methode onContextItemSelected(), die in der Activity definiert werden muss. Die Methoden editItem(cursor, position) und delete(uuid) sind eigene Methoden meines Programms, aus dem der Code entnommen wurde.
@Override
public boolean onContextItemSelected(MenuItem item) {
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
    Cursor cursor = (Cursor)listView.getItemAtPosition(info.position);
    switch (item.getItemId()) {
        case R.id.action_lstchg:
            editItem(cursor, info.position);
            return true;
        case R.id.action_lstdel:
            String uuid = cursor.getString(cursor.getColumnIndexOrThrow(VokDB._ID));
            delete(uuid);
            return true;
        default:
            return super.onContextItemSelected(item);
    }
}

Links


Homepage (C) Copyright 2015, 2016 Arnold Willemer