如何在低版本Android自定义View中获取style标签属性值?
自定义View兼容低版本读取style属性值的方案
核心思路
通过AttributeSet直接读取Android命名空间下的style属性,同时处理主题属性引用的情况,确保兼容API 29以下版本。
具体实现步骤
1. 读取并解析style属性
在自定义View的init块中,先读取布局设置的style值,再处理主题属性引用的场景:
class CustomButton @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = R.style.ButtonStyleLarge ) : AppCompatButton(context, attrs, defStyleAttr) { init { // 读取布局中设置的style属性,默认返回构造方法传入的defStyleAttr val styleAttrId = attrs?.getAttributeResourceValue( "http://schemas.android.com/apk/res/android", "style", defStyleAttr ) ?: defStyleAttr // 解析主题属性,得到实际的style资源ID val resolvedStyleId = resolveStyleId(context, styleAttrId) // 根据style执行对应逻辑 when (resolvedStyleId) { R.style.ButtonStyleLarge -> { // 大样式相关操作 } R.style.ButtonStyleSmall -> { // 小样式相关操作 } else -> { // 默认样式逻辑 } } } /** * 处理主题属性引用(如?attr/buttonStyle),解析出对应的style资源ID */ private fun resolveStyleId(context: Context, attrId: Int): Int { // 判断是否为主题属性(属性ID的最高位标记为0x01) if (attrId and 0x01000000 == 0x01000000) { val typedValue = TypedValue() if (context.theme.resolveAttribute(attrId, typedValue, true)) { return typedValue.resourceId } } return attrId } }
2. 关键细节说明
getAttributeResourceValue()的第一个参数是固定的Android命名空间,第二个参数为属性名"style",第三个参数是默认回退值;- 若布局中设置的
style是主题属性(如?attr/ButtonStyleLarge),直接读取到的是属性ID而非style资源ID,需要通过Theme.resolveAttribute()解析得到实际资源; - 该方案不依赖API 29+的
explicitStyle方法,可兼容所有低版本SDK。
内容的提问来源于stack exchange,提问作者Glimpse
相关产品推荐
相关产品推荐

