如何以编程方式获取强调颜色?

105

如何以编程方式获取样式中设置的强调颜色,像下面这样?

    <item name="android:colorAccent">@color/material_green_500</item>

5
任何想要进行点踩的人都可以放心地在评论中发表自己的想法,但请确保不改变原意。 - Jakob Harteg
9个回答

146

您可以通过以下方式从当前主题中获取它:

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;
}

支持版本是什么? - DariusL
4
这是支持版本。 - rciovati
2
这对我返回了一个负数。这仍然是获取强调颜色的有效方式吗? - Naveed
1
typedValue.data 引用的是什么? - GPack
2
对于那些问为什么该方法返回负数的人,是因为你期望一个十六进制吗?如果是这样,请检查我的答案:https://dev59.com/214c5IYBdhLWcg3wuMN7#49896254 - Esdras Lopez
显示剩余6条评论

53

这对我也起作用:

public static int getThemeAccentColor (final Context context) {
    final TypedValue value = new TypedValue ();
    context.getTheme ().resolveAttribute (R.attr.colorAccent, value, true);
    return value.data;
}

在这个解决方案中,我也遇到了同样的问题,出现了负值,并且它下降 :( - batsheva
2
负值没问题,这是一种颜色! - copolii
但是我的应用程序崩溃了,出现了“没有找到资源”的错误...当我使用常规颜色时,这种情况并不会发生!因此,该值不正确。 - batsheva
如果资源没有找到,那么负值从哪里来的?我的意思是,例如0xff2506ac是负数但也是有效的颜色值。 - copolii
我还发现负值并遇到异常。一个很大的负整数。 - Shamsul Arefin
4
你得到的负数是实际颜色,而不是资源ID。不要将其用作资源ID。 - copolii

31
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;
}

2
这是唯一一个不依赖于导入应用程序 R 类的答案,非常适合构建自定义视图。 - Allan Veloso

24

如果你正在使用Kotlin

@ColorInt
fun Context.themeColor(@AttrRes attrRes: Int): Int = TypedValue()
    .apply { theme.resolveAttribute (attrRes, this, true) }
    .data

12

我在一个工具类上有一个静态方法来获取当前主题的颜色。大多数情况下,这是colorPrimary、colorPrimaryDark和accentColor,但你还可以获得更多的颜色。

@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;
}

9
这是我的看法:
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));
}

使用方法:

    String windowBackgroundHex = getThemeColorInHex(this, "windowBackground", android.R.attr.windowBackground);
    String primaryColorHex = getThemeColorInHex(this, "colorPrimary", R.attr.colorPrimary);

2
String.format()函数可以帮助解释如何将负整数值转换为十六进制颜色字符串。 - Mr-IDE
1
这是一个比接受的答案更好/通用的解决方案! - Nilesh Pawar
还有一个有用的链接:https://dev59.com/Qmw15IYBdhLWcg3wi8dv - Mr-IDE
谢谢您!+1 - null_awe

5
MaterialColors 可以在这种情况下使用,如果您希望它是单行的。
            MaterialColors.getColor(context, R.attr.colorAccent,context.getResources().getColor(R.color.fall_back_color));

第一个参数是上下文,第二个参数是您需要获取的属性,第三个参数是回退颜色,在获取属性颜色时遇到问题或属性缺失时使用。


1
注意:在应用程序中手动设置 applicationContext.setTheme(R.style.AppTheme) 后,此功能才能在服务或应用程序上下文中正常工作。 - Andoctorey

2

Kotlin解决方案:

    context.obtainStyledAttributes(TypedValue().data, intArrayOf(R.attr.colorAccent)).let {
        Log.d("AppLog", "color:${it.getColor(0, 0).toHexString()}")
        it.recycle()
    }

0

当您使用 Theme.Material3 时,必须结合此处提到的两种解决方案,因为一种适用于 R.attr,另一种适用于 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)
}

defaultValue 应该是 -1 而不是 Color.BLUE,对吧?另外,if 条件语句应该检查返回值是否不等于 defaultValue。例如:if (materialColor != defaultValue) - rupinderjeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接