ListView - Backgrounds / Listener - Probleme

T

Tom299

Stammgast
122
Hallo zusammen,

ich hab in meiner Activity eine ListView mit einem Listener, um das selektierte Item abzufragen (Check-Boxen hab ich keine mehr in meiner Zeile drin, d.h. das Event kommt einwandfrei erst mal an und mein Toast wird angezeigt beim Klick):

Code:
        itemsAdapter = new DBItemArrayAdapter(this, R.layout.table_item_new, dbItems);
        listView.setAdapter(itemsAdapter);

        listView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView av, View v, int index, long arg3) {
                //System.out.println("ItemClicked");
                selectedDBItem = dbItems.get(index);
                if (selectedDBItem != null) {
                    Toast itemToast = Toast.makeText(getApplicationContext(), selectedDBItem.getName() + " " + selectedDBItem.getVorname(), Toast.LENGTH_SHORT);
                    itemToast.show();
                }
            }
        });
        
        layout.addView(listView);
Dadurch hat man erst mal ein "Standardlayout mit Standardfarben", wobei hier alle Zeilen die gleiche Farbe haben und die selektierte Zeile wird orange hervorgehoben. Soweit so gut.

Nun will ich aber, daß meine Zeilen abwechselnde Farben haben. Also hab ich in meinem Adapter folgendes eingebaut:

Code:
        final TableRow rowItem = (TableRow)dbItemsView.findViewById(R.id.item_row);
        if (position % 2 == 0) {
            //rowItem.setBackgroundColor(Color.DKGRAY);
            rowItem.setBackgroundColor(colorEven);
        }
        else {
            //rowItem.setBackgroundColor(Color.GRAY);
            rowItem.setBackgroundColor(colorOdd);
        }
Die Zeilen werden zwar nun schön abwechselnd eingefärbt, allerdings wird nun die selektierte Zeile nicht mehr farblich hervorgehoben (keine Standard-Orange-Farbe mehr).

Ok dachte ich mir, dann muß ich das wohl auch selbst übernehmen, also hab ich einen OnTouch-Listener implementiert:
Code:
        rowItem.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    rowItem.setBackgroundColor(Color.YELLOW);
                    return true;
                }
                else if (event.getAction() == MotionEvent.ACTION_UP) {
                    if (position % 2 == 0) {
                        //rowItem.setBackgroundColor(Color.DKGRAY);
                        rowItem.setBackgroundColor(colorEven);
                    }
                    else {
                        //rowItem.setBackgroundColor(Color.GRAY);
                        rowItem.setBackgroundColor(colorOdd);
                    }                    
                    return true;
                }
                else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
                    if (position % 2 == 0) {
                        //rowItem.setBackgroundColor(Color.DKGRAY);
                        rowItem.setBackgroundColor(colorEven);
                    }
                    else {
                        //rowItem.setBackgroundColor(Color.GRAY);
                        rowItem.setBackgroundColor(colorOdd);
                    }                    
                    return true;
                }
                                
                return false;
            }
        });
Damit wird nun meine selektierte Zeile wieder farblich hervorgehoben bzw. beim deselektieren wieder die alte Zeilenfarbe genommen.

Doch nun hab ich das Problem, daß mein OnItemClickListener der ListView nicht mehr funktioniert, da das TouchEvent wohl den Click konsumiert.

Wie kann ich nun das Event weiterreichen, damit der OnItemClickListener weiterhin funktioniert oder wie macht man es richtig in Android?

Mein erster Versuch war, das return-Ergebnis von true auf false im OnTouch-Listener zu setzen. Das scheint prinzipiell zu funktionieren, aber dann funktioniert das deselektieren der Zeile nicht mehr. Also irgendwo bekomm ich momentan immer nen Folgefehler bei meiner Vorgehensweise ...


Gruß,
Tom
 
Hallo Tom,

statt die Farbe manuell zu ändern macht es Sinn 'nen StateListDrawable oder eine ColorStateListResourcezu verwenden, dann kannst du dir das überschreiben der onTouch-Methode - und den verbundenen Problemen - sparen ;)
 
  • Danke
Reaktionen: Tom299
Hallo sixi,

erst mal danke für die Tips. Ich hab mir deine Vorschläge mal angesehen und ein bischen damit rumgespielt. Aber ich glaube, im Endeffekt hilft es mir hier nicht weiter, da ich ja nur eine default-Farbe angeben kann und halt z.b. die pressed-Color. Wenn ich aber 2 unterschiedliche Hintergrundfarben in meiner Liste benutze (gerade und ungerade zeile) dann bekomm ich es damit ja auch nicht mehr richtig zurückgesetzt. Oder hab ich evtl. nen Denkfehler hier? ;-)

Allerdings frage ich mich gerade, ob es evtl. sinnvoller wäre, eine eigene ListView zu schreiben, die sich um die Farben kümmert, anstatt die Farben im Adapter zu setzen. Der Adapter sollte vermutlich eher nur für das Mapping der Daten zu den GUI-Elementen benutzt werden, oder?

Ich werde mir mal ne eigene ListView ableiten und schauen, ob ich hier was drehen kann :)
 
Da brauchste am ListView nichts zu ändern.
In deinem Adapter in der getView-Methode bauste den Teil ein, den du schon hast und änderst ihn ein bisschen:
Code:
        if (position % 2 == 0) {
            v.setBackgroundResource(DEINE_SELECTOR_RESOURCE_GERADE);
        }
        else {
            v.setBackgroundResource(DEINE_SELECTOR_RESOURCE_UNGERADE);
        }
ausgehend davon, dass dein View (der Parameter von getView bzw. wenn du ihn neu verwendest etc.) "v" heißt.
 
  • Danke
Reaktionen: Tom299
Ich habe jetzt mal 2 resource-files angelegt:

even_color_row.xml
Code:
<?xml version="1.0" encoding="utf-8"?>
<selector
      xmlns:android="http://schemas.android.com/apk/res/android">
    <item 
        android:state_pressed="true"
        android:color="@color/table_row_highlight_color">
    </item>
    <item 
        android:color="@color/table_row_color_even">
    </item>
</selector>
odd_color_row.xml
Code:
<?xml version="1.0" encoding="utf-8"?>
<selector
      xmlns:android="http://schemas.android.com/apk/res/android">
    <item 
        android:state_pressed="true" 
        android:color="@color/table_row_highlight_color">
    </item>
    <item 
        android:color="@color/table_row_color_odd">
    </item>    
</selector>
und in meinem Adapter dann eingebunden
Code:
        final TableRow rowItem = (TableRow)dbItemsView.findViewById(R.id.item_row);
        if (position % 2 == 0) {
            //rowItem.setBackgroundColor(colorEven);
            rowItem.setBackgroundResource(R.color.even_color_row);
        }
        else {
            //rowItem.setBackgroundColor(colorOdd);
            rowItem.setBackgroundResource(R.color.odd_color_row);
        }
soweit sollte es doch richtig sein, oder?

aber wenn ich das programm nun starte wird es direkt wieder abgebrochen und ich bekomm den Fehler:
Code:
ERROR/AndroidRuntime(211): Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #7: <item> tag requires a 'drawable' attribute or child tag defining a drawable
ich hab schon geschaut, ob ich innerhalb des Item-Tags ein child- oder drawable-attribut finde, aber leider nichts :confused:
 
ah, ich habs doch noch hinbekommen, pünktlich zum feierabend :)

ich mußte eine drawable resource anlegen:


Code:
<?xml version="1.0" encoding="utf-8"?>
<selector
      xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"
          android:drawable="@color/table_row_highlight_color" /> <!-- pressed -->
    <item android:drawable="@color/table_row_color_even" /> <!-- default -->    
</selector>


und dann in meinem adapter angeben
Code:
rowItem.setBackgroundResource(R.drawable.drawable_even_color);

jetzt klappts endlich :scared:


vielen dank sixi für die tips :)
 

Ähnliche Themen

A
Antworten
10
Aufrufe
1.002
swa00
swa00
S
Antworten
4
Aufrufe
944
Sempervivum
S
D
Antworten
9
Aufrufe
1.722
jogimuc
J
Zurück
Oben Unten