How to specify background color in Color State List Resources?
Asked Answered
H

3

20

To give the user of my app an indication which field currently has the focus I am trying to change the background color of some of my fields depending on the current state, however, I am having troubles understanding Androids Color State List Resources:

I found example (sorry, URL no longer works) and if I try exactly the same, i.e. if I want to adapt the textColor , things do work. However, if I try an only slightly different thing, namely to adapt the background color, things do not work and I don't understand why? Why is this so inconsistent???

To make it simpler to understand what I am trying to do, I append my misc. .xml files:

The AndroidManifest.xml file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="mmo.android.test"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".Test"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest> 

The Test-Activity:

package mmo.android.test;

import android.app.Activity;
import android.os.Bundle;

public class Test extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

The res/values/strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, Test!</string>
    <string name="app_name">Test</string>
</resources>

res/color/button_test_color.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"   android:color="#f0f"/> <!-- pressed -->
    <item android:state_focused="true"   android:color="#ff0"/> <!-- focused -->
    <item android:color="#000"/> <!-- default -->
</selector>

and finally my res/layout/main.xml file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="foobar"
        android:textColor="@color/button_test_color"
        android:background="#f00"
     />
    <!-- 
    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="foobar"
        android:textColor="#f00"
        android:background="@color/button_test_color"
     />
     -->
</LinearLayout>

If I run this as shown here, it works, i.e. I get a button whose text color changes depending on whether the button is focuses, pressed, etc.

If I uncomment the lower button, where I just flipped the attribute values for textColor and background I get an exception, stating

... <item> tag requires a 'drawable' attribute or child tag defining a drawable

What the heck am I missing here? Why is that color state list acceptable as a text color but not as a background color? How does one specify a view's background color depending on the view's state?

Honan answered 17/10, 2010 at 14:25 Comment(0)
A
-1

Try defining textColor as a drawable, rather than a color:

android:textColor="@drawable/button_test_color"

Resource categories are based on what type of resources they are, not the name of the folder they are located in. XML files of the form button_test_color.xml are typically referenced as "drawable" - I'm actually surprised "color" worked at all!

Anodic answered 17/10, 2010 at 21:28 Comment(4)
Form more inf. on using a drawable resource, this question has been asked before.Stansbury
I do not know why this answer has been marked as correct. The questioner appears to have followed the Android docs which indicate that @color should work fine with an xml file in the res/color directory and is referred to by filename.Towering
I'm even more surprised that this was the chosen answer when IT DOESN'T WORK AT ALL. -1Interpreter
Irrelevant and should not be the accepted answer. The OP has a problem with the 'background' attribute using ColorStateList.Gavial
R
67

I had this exact problem. It looks to me like android:background doesn't work with Color State Lists. I got around this by creating a State List Drawable instead (individual colors can be used as drawables in the State List).

To use your example, create a file res/drawable/button_test_background.xml:

<?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/pressed_color"/>
    <item android:state_focused="true"   android:drawable="@color/focused_color"/>
    <item android:drawable="@color/default_color"/>
</selector>

Note the use of android:drawable instead of android:color. Android will use the color resource and make a drawable out of it. To finish this off, you need to add the color resources to your res/values/colors.xml file:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    ...
    <color name="pressed_color">#f0f</color>
    <color name="focused_color">#ff0</color>
    <color name="default_color">#000</color>
    ...
</resources>

You would then refer to this drawable using @drawable/button_test_background instead of @color/button_test_color.

So, in summary, the Color State List works fine for android:textColor, but for android:background the State List Drawable method above is needed.

Raimund answered 8/8, 2013 at 16:54 Comment(1)
Infuriating. Thanks for confirming my suspicion thoughChromatolysis
S
0

The support variant app:background is allowing to use color state lists directly as backgrounds.

For Android 10+, also android:background is working.

Seventeenth answered 17/4, 2018 at 12:49 Comment(1)
This doesnt work. It compiles but it does not change colors. It appears you have to have the state list in the drawableMaryammaryann
A
-1

Try defining textColor as a drawable, rather than a color:

android:textColor="@drawable/button_test_color"

Resource categories are based on what type of resources they are, not the name of the folder they are located in. XML files of the form button_test_color.xml are typically referenced as "drawable" - I'm actually surprised "color" worked at all!

Anodic answered 17/10, 2010 at 21:28 Comment(4)
Form more inf. on using a drawable resource, this question has been asked before.Stansbury
I do not know why this answer has been marked as correct. The questioner appears to have followed the Android docs which indicate that @color should work fine with an xml file in the res/color directory and is referred to by filename.Towering
I'm even more surprised that this was the chosen answer when IT DOESN'T WORK AT ALL. -1Interpreter
Irrelevant and should not be the accepted answer. The OP has a problem with the 'background' attribute using ColorStateList.Gavial

© 2022 - 2024 — McMap. All rights reserved.