如何引用可绘制的样式属性?

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

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

然后,我创build了这样的主题:

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

这种方法效果很好,使我能够轻松地创build和修改几个主题。 问题是, 它似乎只能在视图中使用,而不能在Drawable中使用

例如,从布局中的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 ,但是也是一样的。

我怎么能这样做? 为什么它在视图中工作,而不是在Drawable中? 我无法在文档中的任何位置find此限制…

根据我的经验,不可能在xml drawable中引用一个属性。
为了使你的主题,你需要:

  • 为每个主题创build一个xml drawable。
  • @color标记或#RGB格式直接绘制所需的颜色。

attrs.xml中为您的drawable 创build一个属性。

 <?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> 

使用属性在布局中引用绘图。

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

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

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

尽pipe无法在前棒棒糖设备上引用可绘制的样式属性,但颜色状态列表是可能的。 您可以使用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的旧版本(前棒棒糖)上工作。

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

正如@marmor所言,API 21现在支持这种技术。但对于那些需要支持旧版Android的用户,您可以使用此function。 使用v7支持库,您仍然可以将使用最低SDK级别的应用程序一直使用到7。

v7 Android支持库中的AppCompatImageView具有此function的无bug实现。 只需用AppCompatImageViewreplaceImageView的用法。