Question

I am trying to set up a ListView with items that have varying background colors, so my adapter's getView() method calls setBackgroundResource() with an appropriate drawable resource for the desired background color.

If I use a ColorDrawable that references a ColorStateList as its color, the color for the pressed state from the ColorStateList is not drawn when I tap on the item.

If I use a StateListDrawable that references a ColorDrawable for the pressed state and a different ColorDrawable for the unpressed state, I get the desired highlighting effect when I tap on the item.

I've set up a simple project to demonstrate this. Here is the getView() method from the ListAdapter:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View retval = getLayoutInflater().inflate(android.R.layout.simple_list_item_1, parent, false);
    TextView textView = (TextView)retval.findViewById(android.R.id.text1);
    textView.setText("" + position);

    switch ( position ) {
        case 0:
            retval.setBackgroundResource(R.drawable.list_background_item_0);
            break;

        case 1:
            retval.setBackgroundResource(R.drawable.list_background_item_1);
            break;
    }

    return retval;
}

res/drawable/list_background_item_0.xml:

<color xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/list_background_item_0" />

res/color/list_background_item_0.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:color="@color/list_background_item_0_pressed"/>
    <item android:color="@color/list_background_item_0_default"/>
</selector>

res/drawable/list_background_item_1.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/list_background_item_1_pressed" />
    <item android:drawable="@drawable/list_background_item_1_default" />
</selector>

res/drawable/list_background_item_1_default.xml:

<color xmlns:android="http://schemas.android.com/apk/res/android" 
    android:color="@color/list_background_item_1_default" />

res/drawable/list_background_item_1_pressed.xml:

<color xmlns:android="http://schemas.android.com/apk/res/android" 
    android:color="@color/list_background_item_1_pressed" />

res/values/colors.xml:

<resources>
    <color name="list_background_item_0_default">#FFCCCC</color>
    <color name="list_background_item_0_pressed">#996666</color>
    <color name="list_background_item_1_default">#CCFFCC</color>
    <color name="list_background_item_1_pressed">#669966</color>
</resources>

List item 0 is configured with a ColorDrawable that references a ColorStateList and does not display a highlight when pressed. List item 1 is configured with a StateListDrawable and does display the highlight.

I would much rather use the ColorStateList than the StateListDrawable as it seems cleaner and involves one less file per item type. Is there something I have missed that would let me use this method? If it isn't intended to work as I am expecting, can someone explain why?

Was it helpful?

Solution

Thanks to Luksprog's comment, I've learned that the drawables referenced by the StateListDrawable can be colors from colors.xml. This makes the StateListDrawable solution preferable to the ColorStateList version.

The final solution is...

getView() method:

  • no changes

res/color/list_background_item_0.xml:

  • deleted

res/drawable/list_background_item_0.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@color/list_background_item_0_pressed" />
    <item android:drawable="@color/list_background_item_0_default" />
</selector>

res/drawable/list_background_item_1.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@color/list_background_item_1_pressed" />
    <item android:drawable="@color/list_background_item_1_default" />
</selector>

res/drawable/list_background_item_1_default.xml:

  • deleted

res/drawable/list_background_item_1_pressed.xml:

  • deleted

res/values/colors.xml:

  • no changes

This solution is as clean or cleaner than I expected the ColorStateList version to be had it worked.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top