setViewValue - Wie aktuelle Zeile in ListView? (SimpleCursorAdapter)

  • Antworten:3
  • Bentwortet
Ansgar M
  • Forum-Beiträge: 1.544

25.11.2010, 20:55:49 via Website

Hi,
ich hab ein kleines Problem.

Ausgangsituation (Problemstellung):
Ich habe eine ListView, mit List Items mit je einem ImageView und zwei TextViews. Der Adapter ist ein SimpleCursorAdapter.
Die Daten werden aus der Datenbank geladen. TextViews funktionieren auch. Nur beim Bild gibt es Probleme. Der Name soll aus dem Cursor geladen werden und damit das entsprechende Bild aus den Assets "geangelt" werden:grin:

Lösungsansatz:
Dafür habe ich einen eigenen ViewBinder geschrieben, der die Methode setViewValue überschreibt. Soweit so gut. Nur bekomme ich durch ihn die View (Ich filter dann nach ImageView), den Cursor sowie die Position der View in dem ListItem. Ich brauche aber die Position in der Liste, um den richtigen Bildnamen aus dem Cursor zu bekommen. Deswegen habe ich eine Zählvariable genommen und setze sie immer einen höher und hole den Namen von der "Position der Zählvariable".

Problem (force close) :
Klappt soweit auch ganz gut, bis ich die 100 Elemente "verscrollt" habe, also entweder bis ganz unten gescrollt bin und dann wieder hoch versuche oder ganz oft hin- und hergescrollt hab.. Dann gibt es eine CursorIndexOutOfBoundsException (was an dem hochgezählten Wert 100 liegt, denn diese Zeile gibt es natürlich nicht).

Im Logcat kommt beispielsweise noch die Methode bindView oder setView vor (bei dieser "at.. at.. at..-Auflistung") muss ich die auch noch überschreiben, oder müssen diese Methoden die Position durchreichen? Sollte ich bei der ImageView die getParent()-Methode verwenden um das ListItem zu bekommen, über das ich die Position in der Liste herausfinden kann?

Danke für Antwort und durchlesen!
Ich steh' grad aufm Schlauch, bin langsam Google-müde:grin: und weiß nicht mehr weiter.

Lg Ansgar

P.S. Ich dachte, ich poste erstmal keinen Haufen an Quelltexten, sondern geb euch die Chance es mir so zu erklären:P

— geändert am 25.11.2010, 20:57:53

Antworten
Gelöschter Account
  • Forum-Beiträge: 294

26.11.2010, 08:32:05 via Website

Hallo,

nicht zählen! Mach' es wie folgt (die Namen sind Beispiele und haben keine Bedeutung, die Positionen sind wichtig):

1.) Deine Tabelle hat natürlich eine _id Spalte - die reicht als Zähler ;-)

2.) Nehmen wir an Du fetchst den Cursor mit "select _id, text1, text2, imagename" dann sind dies die ColumnIndex "0, 1, 2, 3".

3.) Dein Row-Layout der ListView hat pro Row drei Spalten "row_text1, row_text2, row_image".

4.) Der Aufruf des SimpleCursorAdapters:

1simpleCursorAdapter = new SimpleCursorAdapter(this,
2 R.layout.row,
3 cursor,
4 new String[] { "text1", "text2", "imagename" },
5 new int[] { R.id.row_text1, R.id.row_text2, R.id.row_image } );

5.) Hinter dem Aufruf des SimpleCursorAdapter und vor dem Aufruf des setListAdapter baust Du Folgendes ein:

1if (simpleCursorAdapter != null) {
2 simpleCursorAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
3
4 public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
5 if (columnIndex == 3) {
6 String imagename = cursor.getString(columnIndex);
7 ImageView imageView = (ImageView) view;
8
9 // Hier holst Du Dein drawable wo immer es herkommt (res, assets, ...)
10
11 imageView.setImageDrawable(drawable);
12 return true;
13 }
14
15 return false;
16
17});
18
19 setListAdapter(simpleCursorAdapter);
20}

Im SimpleCursorAdapter hast Du dann zwar eine Textspalte (imagename) mit einem ImageView (row_image) verknüpft. Mit dem ViewBinder hast Du dann aber die Gelegenheit das selbst zu zeichnen. Mit dem "if (columnindex == 3)" wartest Du ab bis Dein Image an der Reihe ist gezeichnet zu werden. Du kannst auch mit einem instanceOf auf den Typ prüfen das geht aber nur solange nur eine ImageView in einer Row existiert.

Mit "return true" teilst Du Deinen Eingriff mit und Android läßt die Finger von diesem View in dieser Spalte. Soll Android wie gewohnt zeichnen dann reicht "return false".

EDIT: Fast vergessen. Wenn es erheblich weniger Drawables als Tabellenzeilen in der Datenbank gibt dann würde ich ggfs. die Drawables vorab laden und suchbar zwischenspeichern. Dann könntest Du das permanente Laden im ViewBinder verhindern. In dem Fall hättest Du aber sicher keinen Namen in der Tabelle sondern einen Key mit dem Verweis auf eine andere Tabelle ... (ich schweife ab). Es geht nur darum die Performance so niedrig wie möglich zu halten...

Gruß
Harald

— geändert am 26.11.2010, 08:39:33

Antworten
Ansgar M
  • Forum-Beiträge: 1.544

26.11.2010, 16:30:32 via Website

Hey,
so hatte ich es sogar als erstes, nur da hatte ich das Problem, das überall das selbe Bild war:P Habs dann mit einem Zähler gemacht und irgendwo nebenbei den anderen Fehler rausgenommen (immer dasselbe) und dann nur im Kopf behalten: "Ohne Zähler, selbes Bild".. Ist aber nicht so..:grin:
Habs zurückgeändert und es klappt! Super, danke für die Hilfe!

Lg Ansgar

P.S. Jetzt versteh' ich auch, warum eine ListView immer eine "_id"-Zeile im Cursor braucht:grin:

Antworten
Gelöschter Account
  • Forum-Beiträge: 294

26.11.2010, 19:27:35 via Website

Freut mich zu hören.

Na ja, die _id ist halt der Primary Key. Die Cursor im Android sind ja scrollbar, wiederaufsetzbar - was immer Du Dir erträumst. Für diese Möglichkeiten braucht das System halt einen eindeutigen Schlüssel.

"Nothing but the key" ;-)

Gruß
Harald

Antworten