作为参考(主题)以编程方式获取颜色值


116

考虑一下:

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>

因此,主题颜色由主题引用。如何以编程方式获取theme_color(参考)?通常我会使用,getResources().getColor()但在这种情况下不会使用,因为它已被引用!

Answers:


254

这应该做的工作:

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

在调用此代码之前,还请确保将主题应用于“活动”。可以使用:

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

在您的清单或调用中(调用之前setContentView(int)):

setTheme(R.style.Theme_BlueTheme)

在中onCreate()

我已经用您的价值观对其进行了测试,并且效果很好。


谢谢,我无法尝试您的解决方案,但会导致出现错误:stackoverflow.com/questions/17278244/…也许您对此有经验……
塞拉芬

5
无论如何,在您的解决方案中,我得到的是0值颜色(TypedValue {t = 0x0 / d = 0x0})...我不使用声明样式的,而只是引用颜色
塞拉芬

您是否将主题应用于活动?
伊曼纽尔·莫克林

5
如果您不想将主题应用于活动,则可以ContextThemeWrapper使用主题ID 创建一个,然后从中检索主题。
泰德·霍普

1
此方法适用于android X(材质设计)
BlackBlind

43

如果您使用的是Kotlin,请添加到已接受的答案中。

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

然后在您的活动中,您可以

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


2
好的,感谢您的“整合”。我没有用Kotlin,但很有趣。
塞拉芬

5
好吧,它使TypedValue对外界可见。对于颜色,您始终想解析引用声明,所以我有以下内容:(@ColorInt fun Context.getThemeColor(@AttrRes attribute: Int) = TypedValue().let { theme.resolveAttribute(attribute, it, true); it.data }格式不正确,但可以)
milosmns

1
用法将是这样的:val errorColor = context.getThemeColor(R.attr.colorError)
milosmns

更普遍的方式,这也为检索默认值ColorStateList@ColorInt fun Context.getThemeColor(@AttrRes attribute: Int) = obtainStyledAttributes(intArrayOf(attribute)).use { it.getColor(0, Color.MAGENTA) }(从尼克屠夫
gmk57

最终方法,ColorStateList即使引用了另一个主题属性,它也可以检索整个:(fun Context.getThemeColor(@AttrRes attribute: Int): ColorStateList = TypedValue().let { theme.resolveAttribute(attribute, it, true); AppCompatResources.getColorStateList(this, it.resourceId) }单个颜色也将包裹在一起ColorStateList)。
gmk57

24

这对我有用:

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

如果要从中取出十六进制字符串:

Integer.toHexString(color)

这应该返回ColorRes,而不是ColorInt。
Miha_x64

我最终将其与getColorResource(color)一起使用,而不是调用回收站。
Zeek Aran

2

如果要获得多种颜色,可以使用:

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();

2

将此添加到您的build.gradle(应用程序):

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

并将此扩展功能添加到代码中的某个位置:

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

0

这是一个简洁的Java实用程序方法,该方法具有多个属性并返回一个颜色整数数组。:)

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

Java比Kotlin更好吗?
IgorGanapolsky

@IgorGanapolsky哦,老实说,我不知道。我分享了我的代码,因为我知道它可以派上用场了!我不知道Kotlin,我认为Kotlin不会使其性能更好,甚至可能更少的代码行!:P
瓦伦

-1

对于那些希望参考可绘制对象的人,您应该falseresolveRefs

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


变量typedValue指的是什么?
BENN1TH

什么是可变主题。*指的是什么?
BENN1TH
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.