You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 5.0以下版本如何在Drawable中设置主题颜色?

解决Android 5.0(API 21)以下Drawable中使用主题属性的问题

这个坑我之前也踩过!API 21之前的系统确实不支持在Drawable XML里直接引用?attr/开头的主题属性,不过有几个靠谱的解决办法,你可以根据自己的场景挑选:

方案1:通过代码动态设置Drawable颜色

这是最直接的方式,先剥离shape里的颜色依赖,再在代码中动态注入主题颜色:

  1. 先修改你的shape XML,移除solid颜色或者设为临时占位值:
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="@dimen/button_corner_radius" />
</shape>
  1. 在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:

  1. 保持你原来的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>
  1. 在布局文件中给控件设置背景和背景色调:
<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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 02:23:04