Einfache Liste

Eine Liste anzuzeigen macht immer dann Sinn, wenn diese mehr oder weniger dynamisch generiert werden kann. Liegen die Daten also in einem array- oder Listen-Objekt vor kann dieses einfach an einen Adapter übergeben werden, welcher dann, je nach Typ mehr oder weniger vollautomatisch, die Listenanzeige erstellt.

Es wird davon ausgegangen dass ein Projekt SimpleList mit den Standardnamen erstellt wurde.

Grundsätzlich ist zu erwähnen dass diverse Möglichkeiten existieren eine Liste zu erstellen, hier werden die einfachsten Varianten gezeigt.

Android Standardansicht

Für das Layout wird ein ListView-Element verwendet. Dieses kann als einziges Element (statts des Layouts) oder als Kindelement eines Layouts bestehen. Wichtig ist nur die ID für den späteren Zugriff.

activty_main.xml:

<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"
    tools:context="${relativePackage}.${activityClass}" >
 
    <TextView
        android:id="@+id/tvHelloWorld"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
 
    <ListView 
        android:id="@+id/lvsimpleList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/tvHelloWorld" >
    </ListView>
 
</RelativeLayout>

Die Liste soll mit Daten gefüllt werden, welche hier der Einfachheit halber als vordefiniertes Array zur Verfügung stehen. Dies kann durchaus Sinn machen, meistens werden die Daten aber wohl während des Ablaufs generiert. Das ListView-Element muss wieder definiert werden. Diesem wird dann ein Adapter zugeweisen welcher zuvor „erstellt“ wird. Dem Adapter werden hier Android-Standardansichten für die Liste und die Daten übergeben. Ein Adapter wird, vereinfacht ausgedrückt, immer iterrierend pro Datensatz aufgerufen um entsprechend ein Listenelement zu erzeugen. Zu guter letzt wird hier ein OnItemClickListener verwendet, welcher in der MainActivity implementiert wird. So kann dann in der Methode onItemClick auf das Klick-Event eines Listeneintrages reagiert werden.

MainActivity.java:

public class MainActivity extends Activity implements OnItemClickListener {
 
    private final static String TAG = MainActivity.class.getSimpleName();
 
    // Daten für die Liste bereit stellen
    private String[] aData = new String[] {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6" };
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        // Listview initialisieren
        ListView lvSimpleList = (ListView) findViewById(R.id.lvsimpleList);
 
        // Adapter mit Android eigenen Views erstellen und setzen
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, aData);
        lvSimpleList.setAdapter(adapter);
 
        // onItemClicklistener setzen 
        lvSimpleList.setOnItemClickListener(this);
 
    }
 
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
 
        Log.d(TAG, "onItemClick: Position = " + position);
    }
}

Einfache Standardliste

Eigenen Stil nutzen

Die oben beschriebene Variante reicht in den seltensten Fällen aus. Spätestens wenn ein Listeneintrag nicht nur ein Element enthält, unterschiedliche Listenelemente verwendet werden sollen oder einfach nur die Farbe verändert werden soll, wird es notwendig einen „eigenen“ Adapter zu verwenden. Ein eigener Adapter macht es also möglich die Liste zu individualisieren.

Mit File ⇒ New ⇒ Class eine neue Klasse mit dem Namen ListViewAdapter erstellen. Diese neue Klasse erweitert nun den ArrayAdapter welcher im oberen Beispiel benutzt wurde. Hier muss noch der Datentyp der einzutragenden Daten angegeben werden.

Im Adapter werden 3 Felder für den Context, die Layout-Id und die Daten benötigt, welche im Konstruktor initialisiert werden. In der zu überschreibenden Methode getView() findet alles wichtige statt. Hier wird dem View-Element des Adapters zuerst die ID des Listenelementes mit hilfe eines LayoutInflaters übergeben. Dann muss das TextView-Element „geholt“ werden um die Daten einzutragen. Im hier angegebenen Beispiel wird dann noch die Farbe abwechselnd geändert, ausserdem werden die Standardansichten verwendet. Es ist hier natürlich auch möglich eigene Elemente mit mehreren Einträgen zu nutzen.

ListViewAdapter:

// Klasse erweitert ArrayAdapter, Datentyp "String"
public class ListViewAdapter extends ArrayAdapter<String> {
 
    // deklaration der benötigten Felder
    private Context context;
    private int layoutId;
    private String[] items;
 
    public ListViewAdapter(Context context, int layoutId, String[] items) {
        super(context, layoutId, items);
 
        // initialisierung der Felder 
        this.context = context;
        this.layoutId = layoutId;
        this.items = items;
    }
 
    @Override
    public View getView(int position, View view, ViewGroup parent) {
 
        // Layout zuweisen
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        view = inflater.inflate(layoutId, null);
 
        // Daten in TextView-Element eintragen
        TextView tvItem = (TextView) view.findViewById(android.R.id.text1);
        tvItem.setText(items[position]);
 
        // Farbwechsel
        if (position % 2 == 0)
            view.setBackgroundColor(Color.WHITE);
        else
            view.setBackgroundColor(Color.LTGRAY);
 
        // angepasstes View-Element als Rückgabe
        return view;
    }
}

In der Klasse MainActivity ändert sich nur die Deklaration/Definition des Adapters von zuvor ArrayAdapter auf den soeben erstellten ListViewAdapter, welcher ja eine Erweiterung dessen ist.

ListViewAdapter adapter = new ListViewAdapter(this, android.R.layout.simple_list_item_1, aData);

Erweiterte Standardliste

Performance

Bei langen Listen ist es angeraten die View-Elemente im Adapter nur dann neu zu erzeugen wenn sie noch nicht existieren. Dies wird über eine Datenhalter-Klasse bewerkstelligt. Diese innere Klasse enthält alle schon erzeugten Listeneinträge.

ListViewAdapter:

// Klasse erweitert ArrayAdapter, Datentyp "String"
public class ListViewAdapter extends ArrayAdapter<String> {
 
    // deklaration der benötigten Felder
    private Context context;
    private int layoutId;
    private String[] items;
 
    public ListViewAdapter(Context context, int layoutId, String[] items) {
        super(context, layoutId, items);
 
        // initialisierung der Felder 
        this.context = context;
        this.layoutId = layoutId;
        this.items = items;
    }
 
    @Override
    public View getView(int position, View view, ViewGroup parent) {
 
        // Datenhalter erzeugen
        ViewHolder holder = null;
        if (view == null) {
 
            // Datenhalter initialisieren
            holder = new ViewHolder();
 
            // Layout zuweisen
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            view = inflater.inflate(layoutId, null);
 
            // View-Element an Datenhalter übergeben
            holder.listItem = (TextView) view.findViewById(android.R.id.text1);
 
            // angepasstes View-Element an Datenhalter übergeben
            view.setTag(holder);
        }
        else
            holder = (ViewHolder) view.getTag();
 
        // Daten in TextView-Element eintragen
        holder.listItem.setText(items[position]);
 
        // Farbwechsel
        if (position % 2 == 0)
            view.setBackgroundColor(Color.WHITE);
        else
            view.setBackgroundColor(Color.LTGRAY);
 
        // angepasstes View-Element als Rückgabe
        return view;
    }
 
    // innere Datenhalter-Klasse
    static class ViewHolder {
        TextView listItem;
    }
}