wujek
wujek

Reputation: 11040

How to use theme attribute as color selector

I would like to define a color state list for my text field, which by default uses the primaryTextColor and colorAccent when 'activated'. My definition:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:color="?android:attr/colorAccent" android:state_activated="true"/>

    <item android:color="?android:attr/textColorPrimary"/>

</selector>

This doesn't work (I always get some red color, which I guess is the interpretation of the id as argb color).

What can I do to be able to specify the colors which are theme dependent?

Upvotes: 4

Views: 2130

Answers (3)

Grzesiek Eman
Grzesiek Eman

Reputation: 86

What I did to achieve this, was first create custom values/attrs.xml

<attr name="textOnSelector" type="reference"/>

Then define it's values in a values/themes/themes.xml

<item name="textOnSelector">@color/nice_grey_input</item>

Then finally, calling it from the selector, res/color/selector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_selected="true" android:color="?attr/colorAccent"/>
     <item android:state_selected="false" android:color="?attr/textOnSelector"/>
</selector>

This way I was able to get an item selected within recyclerView, but compatibile with theme changes, regardless of minimum API.

enter image description here

Upvotes: 0

Henry
Henry

Reputation: 17841

I know this is an old post, but still. You can use theme attributes and even the alpha property if your min version is API 23 or above.

From official documentation:

Each item must define an android:color attribute, which may be an HTML-style hex color, a reference to a color resource, or -- in API 23 and above -- a theme attribute that resolves to a color.

Starting with API 23, items may optionally define an android:alpha attribute to modify the base color's opacity. This attribute takes a either floating-point value between 0 and 1 or a theme attribute that resolves as such. The item's overall color is calculated by multiplying by the base color's alpha channel by the alpha value.

Upvotes: 1

Marcin Koziński
Marcin Koziński

Reputation: 11044

I believe it is impossible from XML right now. I know that Android framework only added support for theme attributes in drawable resources in Lollipop and it doesn't work below API 21. I believe that color resources never got the support.

However, you can do that from code!

final TypedArray attributes =
        itemView.getContext().obtainStyledAttributes(R.styleable.WowSdkSongViewHolder);
try {
    int colorAccent =
            attributes.getColor(R.styleable.WowSdkSongViewHolder_colorAccent, 0);
    final int textColorPrimary = attributes.getColor(
            R.styleable.WowSdkSongViewHolder_android_textColorPrimary, 0);

    title.setTextColor(new ColorStateList(
            new int[][] { ThemeUtils.ACTIVATED_STATE_SET, ThemeUtils.EMPTY_STATE_SET },
            new int[] { colorAccent, textColorPrimary }));
} finally {
    attributes.recycle();
}

First you need to get values for attributes in the current theme as you'd normally do. Then you have to create a ColorStateList object. The constructor accepts an array of state lists (actually state arrays, that's way it's int[][]) and an array of corresponding colours. Then you can set this ColorStateList on your TextView with a setTextColor overload.

AppCompat has some handy constants defined in ThemeUtils. However, this class is hidden and in an internal package, so I suggest copying what you need to your own ThemeUtils.

Upvotes: 1

Related Questions