当它是一个引用(主题)时,以编程方式获取颜色值

想想这个:

Xml

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

Xml

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

Xml

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

因此主题引用了 主题颜色。我如何以编程方式获得主题 _ color (引用) ?通常我会使用 getResources().getColor(),但是在这种情况下不会,因为它被引用了!

113900 次浏览

这应该可以起作用:

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

我用你的价值观测试过,效果很好。

这对我很有效:

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)

如果你想得到多种颜色,你可以使用:

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

如果你用的是 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))

下面是一个简洁的 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;
}

对于那些正在寻找一个可绘制的参考,你应该使用 resolveRefs中的 false

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

把这个添加到 build.gradle (app) :

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

我们可以使用 Material Design 库提供的实用工具类:

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

注意: 如果属性提供给 u,则 Color.BLACK是默认颜色

2021/January/8

如果要从主题属性获取颜色,请使用以下步骤。

创建一个变量 my _ color 并将主题属性中的颜色存储为,

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

代替 <VIEWOBJECT>,传递一个视图对象到您想要使用颜色的地方(在幕后,它只是用来获取上下文作为 <VIEWOBJECT>.getContext(),这样它就可以访问资源,即主题属性值)。使用要访问的属性的名称代替 <YOURATTRIBUTENAME>

例子一:

如果您希望从某些活动获得由主题属性引用的颜色。 创建一个变量,该变量表示要在其上使用颜色的视图对象。 这里我在我的活动中有一个 textView,我只是在 textview变量中引用它的对象,然后将它传递给 getColor方法,在后台它将使用这个对象来获取上下文,这样它就可以访问主题属性值

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

例二:

如果您想从自定义视图中的主题属性获取颜色,那么只需使用,

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

在自定义视图 this中引用自定义视图的对象,该对象实际上是一个视图对象。

我用这个 Kotlin 分机

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

样本

getColorFromAttr(android.R.attr.textColorSecondary)

对我来说,它只能使用 ContextCompattypedValue.resourceId

正如在这个问题中提出的: 如何以编程方式获取颜色属性值

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