How to get accent color programmatically?
Asked Answered
A

9

105

How would one fetch the accent color set in styles, like below, programmatically?

    <item name="android:colorAccent">@color/material_green_500</item>
Apterygial answered 22/12, 2014 at 22:8 Comment(1)
Anyone down-voting should feel very free indeed to post their thoughts in comment...Apterygial
T
146

You can fetch it from the current theme in this way:

private int fetchAccentColor() {
    TypedValue typedValue = new TypedValue();

    TypedArray a = mContext.obtainStyledAttributes(typedValue.data, new int[] { R.attr.colorAccent });
    int color = a.getColor(0, 0);

    a.recycle();

    return color;
}
Trigeminal answered 22/12, 2014 at 22:14 Comment(11)
What about the support version?Sidonius
This is the support version.Trigeminal
can we set RGB string in colorPrimary in styles.xml or colors.xml??Brassica
This is returning a negative number for me. Is this still the valid way to get the accent color?Vaisya
What typedValue.data does reference to?Chiastic
I am too getting a negative value. IS there any solution for this.Majorette
@Vaisya Re: negative numbers: color ints can be negative, that's fine.Humphreys
I get same problem negetive value, and it falls :(Oncoming
For the people asking why is the method returning a negative number, is it because you expect a hex? If so, check my answer: https://mcmap.net/q/204032/-how-to-get-accent-color-programmaticallyHartmann
This returns for me the color for my app's theme rather than the custom button theme I want to call it for. How do I call for subthemes?Catheycathi
@Trigeminal is it possible we can set accent color programmatically?Dusty
W
53

This also worked for me:

public static int getThemeAccentColor (final Context context) {
    final TypedValue value = new TypedValue ();
    context.getTheme ().resolveAttribute (R.attr.colorAccent, value, true);
    return value.data;
}
Wise answered 28/2, 2015 at 2:37 Comment(6)
I get same problem also in this solution, negetive value, and it falls :(Oncoming
Negative value is fine. It's a color!Wise
but my aplication craches down with eroor no resource found ... this is not happenning when i put a regular color! so the value is not fineOncoming
Then where is the negative value coming from if the resource is not found? All I'm saying is that 0xff2506ac (for example) is negative number and a valid color value.Wise
I also find negative value and facing exception. a large negative integerCompliment
The negative value that you get is the actual color not the resource id. Don't use it as a resource id.Wise
M
32
private static int getThemeAccentColor(Context context) {
    int colorAttr;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        colorAttr = android.R.attr.colorAccent;
    } else {
        //Get colorAccent defined for AppCompat
        colorAttr = context.getResources().getIdentifier("colorAccent", "attr", context.getPackageName());
    }
    TypedValue outValue = new TypedValue();
    context.getTheme().resolveAttribute(colorAttr, outValue, true);
    return outValue.data;
}
Matrix answered 24/3, 2016 at 3:27 Comment(1)
This is the only answer that do not rely on importing the app R class, which is ideal for building custom views.Epiphyte
P
24

For those of you using Kotlin

@ColorInt
fun Context.themeColor(@AttrRes attrRes: Int): Int = TypedValue()
    .apply { theme.resolveAttribute (attrRes, this, true) }
    .data
Parisparish answered 8/4, 2019 at 12:43 Comment(0)
D
12

I have an static method on a utils class to get the colors from the current theme. Most of times is colorPrimary, colorPrimaryDark and accentColor, but you can get a lot more.

@ColorInt
public static int getThemeColor
(
        @NonNull final Context context,
        @AttrRes final int attributeColor
)
{
    final TypedValue value = new TypedValue();
    context.getTheme ().resolveAttribute (attributeColor, value, true);
    return value.data;
}
Damico answered 6/2, 2016 at 22:16 Comment(0)
H
9

Here's my take on this:

public static String getThemeColorInHex(@NonNull Context context, @NonNull String colorName, @AttrRes int attribute) {
    TypedValue outValue = new TypedValue();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        context.getTheme().resolveAttribute(attribute, outValue, true);
    } else {
        // get color defined for AppCompat
        int appCompatAttribute = context.getResources().getIdentifier(colorName, "attr", context.getPackageName());
        context.getTheme().resolveAttribute(appCompatAttribute, outValue, true);
    }
    return String.format("#%06X", (0xFFFFFF & outValue.data));
}

Usage:

    String windowBackgroundHex = getThemeColorInHex(this, "windowBackground", android.R.attr.windowBackground);
    String primaryColorHex = getThemeColorInHex(this, "colorPrimary", R.attr.colorPrimary);
Hartmann answered 18/4, 2018 at 9:37 Comment(4)
The String.format() helps to explain how to convert the negative integer value to a hex color string.Copulative
This is a much better / generic solution than the accepted answer for this question!Gretel
Also useful: #6540379Copulative
Thank you for this! +1Norsworthy
A
5

The MaterialColors could be used in this case if you want it to be single line

            MaterialColors.getColor(context, R.attr.colorAccent,context.getResources().getColor(R.color.fall_back_color));

The first argument is the context the second argument is the attribute you need to get and the third argument is the fallback color incase the attribute is missing or something goes wrong while getting the attribute color

Anaheim answered 6/1, 2021 at 4:31 Comment(1)
One note. This will not work from service or application context until you set manually in App: applicationContext.setTheme(R.style.AppTheme).Cid
D
2

Kotlin solution:

    context.obtainStyledAttributes(TypedValue().data, intArrayOf(R.attr.colorAccent)).let {
        Log.d("AppLog", "color:${it.getColor(0, 0).toHexString()}")
        it.recycle()
    }
Delwin answered 7/10, 2019 at 22:19 Comment(0)
C
0

When you use Theme.Material3 you have to combine both solutions mentioned here because one works for R.attr and another one for android.R.attr.

@ColorInt
fun Context.getThemeColor(@AttrRes attrRes: Int): Int {
    val materialColor = MaterialColors.getColor(this, attrRes, Color.BLUE)
    if (materialColor< 0) return materialColor

    val resolvedAttr = TypedValue()
    theme.resolveAttribute(attrRes, resolvedAttr, true)
    val colorRes = resolvedAttr.run { if (resourceId != 0) resourceId else data }
    return ContextCompat.getColor(this, colorRes)
}
Cid answered 10/12, 2021 at 10:1 Comment(1)
Shouldn't the defaultValue be something like -1 instead of Color.BLUE? Also, the if condition should check if returned value is not defaultValue. e.g. if (materialColor != defaultValue)Valleau

© 2022 - 2024 — McMap. All rights reserved.