android - 如何从drawable引用样式属性?

我想为我的应用程序提供2个可选主题。 为了做到这一点,我定义了一些属性,如下所示:

 <attr format="color" name="item_background" />

然后,我创建了两个主题,如下所示:

  <style name="ThemeA">
     <item name="item_background">#123456</item>
 </style>

 <style name="ThemeB">
     <item name="item_background">#ABCDEF</item>
 </style>

这种方法效果很好,允许我轻松创建和修改几个主题。 问题是它似乎只能在Views中使用,而不能在Drawables中使用。

例如,引用布局内View的值可以:

 <TextView android:background="?item_background" />

但是在Drawable中做同样的事情并不是:

 <shape android:shape="rectangle">
     <solid android:color="?item_background" />
 </shape>

运行应用程序时出现此错误:

    java.lang.UnsupportedOperationException: Can't convert to color: type=0x2

如果我使用硬编码颜色代替?item_background,它可以工作,但这不允许我使用我的主题。 我也试过?attr:item_background,但同样的事情发生了。

我怎么能这样做? 为什么它在Views中有效但在Drawables中无效? 我在文档中的任何地方都找不到这个限制......

4个解决方案
150 votes

根据我的经验,无法在xml drawable中引用属性。
为了使您的主题成为您需要:

  • 每个主题创建一个xml drawable。
  • 使用@color标签或#RGB格式直接绘制所需的颜色。

在attrs.xml中为drawable创建一个属性。

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <!-- Attributes must be lowercase as we want to use them for drawables -->
   <attr name="my_drawable" format="reference" />
</resources>

将drawable添加到theme.xml中。

<style name="MyTheme" parent="@android:style/Theme.NoTitleBar">
   <item name="my_drawable">@drawable/my_drawable</item>
</style>

使用您的属性在布局中引用您的drawable。

<TextView android:background="?my_drawable" />
L. G. answered 2019-09-11T08:51:24Z
15 votes

lollipop(API 21)开始支持此功能,请参阅[https://code.google.com/p/android/issues/detail?id=26251]

但是,如果您的目标是没有棒棒糖的设备,请不要使用它,因为它会崩溃,而是使用接受的答案中的变通方法。

marmor answered 2019-09-11T08:51:56Z
4 votes

虽然不可能在Lollipop前设备上引用drawables的样式属性,但它可以用于颜色状态列表。 您可以使用Android支持库中的AppCompatResources.getColorStateList(Context context,int resId)方法。 缺点是您必须以编程方式设置这些颜色状态列表。

这是一个非常基本的例子。

彩色/ my_color_state.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_checked="true" android:color="?colorControlActivated" />
  <item android:color="?colorControlNormal" />
</selector>

需要颜色状态列表的小部件:

<RadioButton
  android:id="@+id/radio_button"
  android:text="My Radio" />

而最重要的是:

ColorStateList csl = AppCompatResources.getColorStateList(context, R.color.my_color_state);    
RadioButton r = (RadioButton) findViewById(R.id.radio_button);
r.setTextColor(csl);

好吧,不是最优雅或最短的方式,但这是Android支持库使其适用于Android的旧版本(前Lollipop)。

不幸的是,drawables的类似方法不适用于样式属性。

rubo answered 2019-09-11T08:53:06Z
0 votes

正如@marmor所说,现在API 21支持这一点。但对于那些需要支持旧版Android的用户,您可以使用此功能。 使用v7支持库,您仍然可以在最低SDK级别的应用程序中使用它。

v7 Android支持库中的AppCompatImageView具有此功能的无错误实现。 只需使用AppCompatImageView更新您的ImageView用法。

Benjamin answered 2019-09-11T08:53:41Z
translate from https://stackoverflow.com:/questions/8041537/how-to-reference-style-attributes-from-a-drawable