Android 5.0以下版本如何在Drawable中设置主题颜色?
解决Android 5.0(API 21)以下Drawable中使用主题属性的问题
这个坑我之前也踩过!API 21之前的系统确实不支持在Drawable XML里直接引用?attr/开头的主题属性,不过有几个靠谱的解决办法,你可以根据自己的场景挑选:
方案1:通过代码动态设置Drawable颜色
这是最直接的方式,先剥离shape里的颜色依赖,再在代码中动态注入主题颜色:
- 先修改你的shape XML,移除solid颜色或者设为临时占位值:
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:radius="@dimen/button_corner_radius" /> </shape>
- 在Activity/Fragment里获取主题属性对应的颜色,再设置给Drawable:
// 获取主题中background_1对应的颜色值 TypedValue typedValue = new TypedValue(); getTheme().resolveAttribute(R.attr.background_1, typedValue, true); int targetColor = ContextCompat.getColor(this, typedValue.resourceId); // 获取Drawable并设置颜色 Drawable buttonDrawable = AppCompatResources.getDrawable(this, R.drawable.shape_button); buttonDrawable.setColorFilter(targetColor, PorterDuff.Mode.SRC_IN); // 给目标View设置处理后的Drawable yourButton.setBackground(buttonDrawable);
如果用Kotlin的话代码会更简洁:
val typedValue = TypedValue() theme.resolveAttribute(R.attr.background_1, typedValue, true) val targetColor = ContextCompat.getColor(this, typedValue.resourceId) val buttonDrawable = AppCompatResources.getDrawable(this, R.drawable.shape_button)?.apply { setColorFilter(targetColor, PorterDuff.Mode.SRC_IN) } yourButton.background = buttonDrawable
方案2:使用AppCompat的backgroundTint属性(推荐)
如果你用的是AppCompat系列控件(比如androidx.appcompat.widget.AppCompatButton),可以直接利用兼容库的backgroundTint特性,完全不用改原shape:
- 保持你原来的shape XML不变:
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="?attr/background_1" /> <corners android:radius="@dimen/button_corner_radius" /> </shape>
- 在布局文件中给控件设置背景和背景色调:
<androidx.appcompat.widget.AppCompatButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/your_shape_file" app:backgroundTint="?attr/background_1" />
AppCompat会自动处理API21以下的兼容逻辑,把主题属性对应的颜色应用到背景上,省心又灵活,还能适配动态主题切换。
方案3:为不同API版本创建Drawable文件
如果不想写代码,也可以通过资源目录区分版本实现静态兼容:
- 在
res/drawable/下创建shape文件,使用固定颜色(API21以下的默认颜色) - 在
res/drawable-v21/下创建同名shape文件,保留?attr/background_1主题属性引用
不过这个方案的局限性很明显:如果主题属性颜色是动态变化的(比如深色/浅色主题切换),静态资源就没法适配了,所以更推荐前两种方案。
另外要注意,确保你的Activity继承自AppCompatActivity,并引入AndroidX AppCompat库,这样所有兼容特性才能正常生效。
内容的提问来源于stack exchange,提问作者K. B
相关产品推荐
相关产品推荐

