ListView ist für Anfänger nicht wirklich einfach - nach vielen Fragen im Forum hab ich nun mal ein Tutorial dazu gemacht. Ich gehe dabei auch auf einige andere Punkte ein, die bei Anfängern gerne mal Probleme bereiten.
Zunächst mal die grobe Übersicht:
ListView ist ein vertikal scrollendes Widget, das von einem Adapter die Listeneinträge aufbauen läßt und diese dann anzeigt. Dabei werden nur so viele Einträge erzeugt, bis der Bildschirm voll ist (und noch ein bisschen weiter).
Wenn der Benutzer dann scrollt, werden vom ListView die benötigten Einträge vom Adapter nachgeladen (das habt ihr bestimmt schon bei einigen Apps bemerkt).
Es gibt zwar einige spezialisierte Adapter (z.B. ArrayAdapter, CursorAdapter), aber ich nutze hier den BaseAdapter, da sieht man besser, was intern passiert.
Die Daten verpacke ich in eine Klasse Datensatz, mehrere Datensätze kommen in eine ArrayList<Datensatz>. Diese ArrayList nutzt dann der BaseAdapter mit einem Layout und erzeugt die List-Einträge.
Nun geht's los:
Zunächst brauchen wir eine Datenstruktur für die Informationen, die in einem Listeneintrag eingebaut werden ("Datensatz").
private class Datensatz {
public String name; // besser setter und getter-Methoden schreiben, stört hier aber...
public String datum; // die Umwandlung von Datum lasse ich weg - das ist ein anderes (großes) Problem
public Datensatz(String name, String datum) {
this.name = name;
this.datum = datum;
}
}
Die Datensätze kommen in eine ArrayList, diese benutzt dann der Adapter, um die einzelnen Views zu erzeugen. Die Variable datensaetze gilt für die ganze Activity:
private ArrayList<Datensatz> datensaetze;
private void initDatensaetze() {
datensaetze = new ArrayList<Datensatz>();
for (int i=0; i<nameArray.length; i++) {
// hier aus Arrays auslesen, bei dir wahrscheinlich anders...
Datensatz datensatz = new Datensatz(nameArray[i],datumArray[i]);
datensaetze.add(datensatz);
}
}
Alles anzeigen
Damit ein Datensatz in der Liste als View-Element eingebaut werden kann, brauchst du ein Layout. Ich hab hier mal ein Beispiel mit ein paar nützlichen Formatierungen (speichern in Projekt/res/layout/mylistitemlayout.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:id="@+id/Zeile1Container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/Nummer"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal" />
<TextView
android:id="@+id/Datum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal" />
</LinearLayout>
<LinearLayout
android:id="@+id/Zeile2Container"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/Name"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
Alles anzeigen
Nun kommt der Adapter, der dem ListView die einzelnen ListItems auf Anfrage liefert. Der Adapter muss auch ein getCount liefern, damit ListView weiß, wann Schluss ist. Außerdem braucht man meistens auch einen OnItemClickListener (dann dürfen die Items aber selber keine OnClickListener implementieren!). Meine Activity heißt übrigens MyListActivity - musst du wahrscheinlich anpassen.
class MyItemAdapter extends BaseAdapter implements OnItemClickListener {
private final LayoutInflater mInflater;
public MyItemAdapter() {
mInflater = (LayoutInflater) MyListActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return datensaetze.size();
}
public Datensatz getItem(int position) {
return datensaetze.get(position);
}
public long getItemId(int position) {
return (long) position;
}
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout itemView = (LinearLayout) mInflater.inflate(R.layout.mylistitemlayout, parent, false);
bindView(itemView, position);
return itemView;
}
private void bindView(LinearLayout view, int position) {
Datensatz datensatz = getItem(position);
view.setId((int) getItemId(position));
TextView nummerTextView = (TextView) view.findViewById(R.id.Nummer);
TextView datumTextView = (TextView) view.findViewById(R.id.Datum);
TextView nameTextView = (TextView) view.findViewById(R.id.Name);
nummerTextView.setText(String.valueOf(position));
datumTextView.setText(datensatz.datum);
nameTextView.setText(datensatz.name);
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Meldung ausgeben oder Intent bauen und Activity starten
Datensatz gewaehlterDatensatz = datensaetze.get(position);
}
}
Alles anzeigen
Jetzt brauchen wir noch ein Layout für die MyListActivity:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:id="@+id/UeberschriftContainer"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/Ueberschrift"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal" />
</LinearLayout>
<ListView
android:id="@+id/ListView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
Alles anzeigen
So, nun der krönende Abschluss in MyListActivity: Layout laden, Daten aufbauen, ListView mit dem Adapter verbinden:
public class MyListActivity extends Activity {
private MyItemAdapter myAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylistlayout);
initDatensaetze();
ListView l = (ListView) findViewById(R.id.ListView1);
myAdapter = new MyItemAdapter();
l.setAdapter(myAdapter);
l.setOnItemClickListener(myAdapter);
}
@Override
protected void onResume() {
super.onResume();
// falls wir vom Änderungsformular zurückkommen...
myAdapter.notifyDataSetChanged();
}
// hier die Java-Quelltext-Schnipsel von weiter oben einfügen:
// Datensatz
// initDatensaetze
// MyItemAdapter
}
Alles anzeigen
Jetzt hab ich hoffentlich alles zusammen - leider muss man sich das aus verschiedenen Quellen zusammen sammeln und Anfänger haben da manchmal zu viele lose Enden in der Hand. Aber hiermit solltest du klar kommen - Erweiterungsmöglichkeiten sind vor allem in Datensatz und bindView sinnvoll, je nach Quelle der Daten ist initDatensaetze auch einfach anzupassen.
Fehler und Verbesserungen sind willkommen.