我想为我的应用程序提供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>
此方法效果很好,允许我轻松创建和修改多个主题。问题是似乎只能在视图中使用,而不能在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中无效?我在the documentation ...
中的任何地方都找不到此限制答案 0 :(得分:151)
根据我的经验,无法在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" />
答案 1 :(得分:15)
从lollipop
(API 21)开始支持此功能,请参阅
https://code.google.com/p/android/issues/detail?id=26251
但是,如果您在没有棒棒糖的情况下定位设备,请不要使用它,因为它会崩溃,而是使用已接受答案中的变通方法。
答案 2 :(得分:4)
虽然不可能在 pre-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的similar method不适用于样式属性。
答案 3 :(得分:1)
我在https://stackoverflow.com/a/59467269/3841352中回答了相同的问题,但我也会在此处发布:
我遇到了同样的问题,截至2019年,该问题尚未解决,因此您无法在选择器中将属性作为可绘制对象进行引用。我将分享解决该问题的方法,因为我在此处看不到它。我在bug report的最后一条评论中找到了它。
解决方法基本上是创建一个可绘制资源,该资源将是引用属性值的资源。
为说明您的情况,解决方案将改为:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?attr/colorPrimary" android:state_enabled="true" android:state_window_focused="false"/>
<item android:drawable="?attr/colorPrimaryDark" android:state_pressed="true"/>
<item android:drawable="@android:color/darker_gray" android:state_enabled="false"/>
<item android:drawable="?attr/colorPrimary"/>
</selector>
您将?attr / *替换为可绘制资源:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/colorPrimaryDrawable" android:state_enabled="true" android:state_window_focused="false"/>
<item android:drawable="@drawable/colorPrimaryDarkDrawable" android:state_pressed="true"/>
<item android:drawable="@android:color/darker_gray" android:state_enabled="false"/>
<item android:drawable="@drawable/colorPrimaryDrawable"/>
</selector>
可绘制对象定义为:
drawable / colorPrimaryDrawable
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle">
<solid android:color="?attr/colorPrimary" />
</shape>
drawable / colorPrimaryDarkDrawable
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle">
<solid android:color="?attr/colorPrimaryDark" />
</shape>
希望有帮助!
答案 4 :(得分:0)
正如@marmor所说,现在API 21支持这一点。但对于那些需要支持旧版Android的用户,可以使用此功能。使用v7支持库,您仍然可以在SDK级别最低的应用程序中使用它。
v7 Android支持库中的AppCompatImageView
具有此功能的无错误实现。只需将ImageView
的用法替换为AppCompatImageView
。