Get color value programmatically when it's a reference (theme)

Consider this:

styles.xml

<style name="BlueTheme" parent="@android:style/Theme.Black.NoTitleBar">
    <item name="theme_color">@color/theme_color_blue</item>
</style>

attrs.xml

<attr name="theme_color" format="reference" />

color.xml

<color name="theme_color_blue">#ff0071d3</color>

So the theme color is referenced by the theme. How can I get the theme_color (reference) programmatically? Normally I would use getResources().getColor() but not in this case because it’s referenced!

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

This should do the job:

TypedValue typedValue = new TypedValue();
Theme theme = context.getTheme();
theme.resolveAttribute(R.attr.theme_color, typedValue, true);
@ColorInt int color = typedValue.data;

Also make sure to apply the theme to your Activity before calling this code. Either use:

android:theme="@style/Theme.BlueTheme"

in your manifest or call (before you call setContentView(int)):

setTheme(R.style.Theme_BlueTheme)

in onCreate().

I’ve tested it with your values and it worked perfectly.

Solution 2

To add to the accepted answer, if you’re using kotlin.

@ColorInt
fun Context.getColorFromAttr(
    @AttrRes attrColor: Int,
    typedValue: TypedValue = TypedValue(),
    resolveRefs: Boolean = true
): Int {
    theme.resolveAttribute(attrColor, typedValue, resolveRefs)
    return typedValue.data
}

and then in your activity you can do

textView.setTextColor(getColorFromAttr(R.attr.color))

Solution 3

We can use the utility class provided by Material Design library:

int color = MaterialColors.getColor(context, R.attr.theme_color, Color.BLACK)

NOTE: Color.BLACK is the default color in case the attribute supplied to the u

Solution 4

This worked for me:

int[] attrs = {R.attr.my_attribute};
TypedArray ta = context.obtainStyledAttributes(attrs);
int color = ta.getResourceId(0, android.R.color.black);
ta.recycle();

if you want to get the hexstring out of it:

Integer.toHexString(color)

Solution 5

2021/January/8

If you want to get color from theme attributes, use the following steps.

Create a variable my_color and store the color from theme attributes as,

val my_color = MaterialColors.getColor(<VIEWOBJECT>, R.attr.<YOUATRRIBUTENAME>)

In place of <VIEWOBJECT>, pass a view object where you want to use the color, (behind the scenes it’s just used to get the context as <VIEWOBJECT>.getContext() so that it can access resource i.e theme attribute values) . In place of <YOURATTRIBUTENAME>, use the name of the atrribute that you want to access

Example 1:

If you want want to get color referenced by theme attributes from certain activity.
Create a variable that represents a view object on which you want to use the color.
Here i have a textView in my activity, i’ll just reference its object inside textview variable and pass it to the getColor method and behind the scenes it’ll use that object to just get the context, so that it can access theme attribute values

val textview: TextView = findViewById(R.id.mytextview)
val my_color = MaterialColors.getColor(textView, R.attr<YOURATTRIBUTENAME>)

Example 2 :

If you want to get color from theme attributes inside a custom view then just use,

val my_color = MaterialColors.getColor(this, R.attr.<YOUATRRIBUTENAME>)

Inside a custom view this refers to the object of the custom view, which is in fact a view object.

Solution 6

Add this to your build.gradle (app):

implementation 'androidx.core:core-ktx:1.1.0'

And add this extension function somewhere in your code:

@ColorInt
@SuppressLint("Recycle")
fun Context.themeColor(
    @AttrRes themeAttrId: Int
): Int {
    return obtainStyledAttributes(
        intArrayOf(themeAttrId)
    ).use {
        it.getColor(0, Color.MAGENTA)
    }
}

Solution 7

I use this kotlin extension

@ColorInt
fun Context.getColorFromAttr( @AttrRes attrColor: Int
): Int {
    val typedArray = theme.obtainStyledAttributes(intArrayOf(attrColor))
    val textColor = typedArray.getColor(0, 0)
    typedArray.recycle()
    return textColor
}

sample

getColorFromAttr(android.R.attr.textColorSecondary)

Solution 8

If you want to get multiple colors you can use:

int[] attrs = {R.attr.customAttr, android.R.attr.textColorSecondary, 
        android.R.attr.textColorPrimaryInverse};
Resources.Theme theme = context.getTheme();
TypedArray ta = theme.obtainStyledAttributes(attrs);

int[] colors = new int[attrs.length];
for (int i = 0; i < attrs.length; i++) {
    colors[i] = ta.getColor(i, 0);
}

ta.recycle();

Solution 9

Here’s a concise Java utility method that takes multiple attributes and return an array of color integers. 🙂

/**
 * @param context    Pass the activity context, not the application context
 * @param attrFields The attribute references to be resolved
 * @return int array of color values
 */
@ColorInt
static int[] getColorsFromAttrs(Context context, @AttrRes int... attrFields) {
    int length = attrFields.length;
    Resources.Theme theme = context.getTheme();
    TypedValue typedValue = new TypedValue();

    @ColorInt int[] colorValues = new int[length];

    for (int i = 0; i < length; ++i) {
        @AttrRes int attr = attrFields[i];
        theme.resolveAttribute(attr, typedValue, true);
        colorValues[i] = typedValue.data;
    }

    return colorValues;
}

Solution 10

For those who are looking for reference to a drawable you should use false in resolveRefs

theme.resolveAttribute(R.attr.some_drawable, typedValue, **false**);

Solution 11

With me it only worked using ContextCompat and the typedValue.resourceId

As proposed in this question: How to get a value of color attribute programmatically

TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(R.attr.colorControlNormal, typedValue, true);
int color = ContextCompat.getColor(this, typedValue.resourceId)

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply