Android自定义属性配合selector选择器使用不生效如何解决
核心错误
你没有将自定义属性的运行时值同步到View的Drawable状态体系中。Android的Selector不会主动读取你通过TypedArray拿到的自定义属性值,它的规则匹配完全依赖View维护的Drawable状态集,自定义属性默认不会被加入这个状态集,所以Selector永远无法匹配到你写的规则。
修复步骤
- 声明对应自定义状态
在原有attrs配置中补充自定义状态的声明,Selector匹配依赖这个状态标识:
- 声明对应自定义状态
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- 自定义状态声明,供Selector匹配使用 --> <attr name="state_mycustom" format="boolean"/> <declare-styleable name="MyComponent"> <attr name="mycustom" format="boolean"/> </declare-styleable> </resources>
- 自定义View中同步状态
在MyComponent类中重写onCreateDrawableState方法,把自定义属性的当前值合并到Drawable状态集;同时在属性值变化时主动调用refreshDrawableState()触发状态刷新:
- 自定义View中同步状态
public class MyComponent extends View { private boolean isMyCustom = false; public MyComponent(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyComponent); isMyCustom = typedArray.getBoolean(R.styleable.MyComponent_mycustom, false); typedArray.recycle(); } // 动态修改mycustom属性值后必须调用refreshDrawableState()触发状态更新 public void setMyCustom(boolean value) { if (isMyCustom != value) { isMyCustom = value; refreshDrawableState(); } } @Override protected int[] onCreateDrawableState(int extraSpace) { // 预留1个位置存储自定义状态 int[] states = super.onCreateDrawableState(extraSpace + 1); // 合并自定义状态到状态集 if (isMyCustom) { mergeDrawableStates(states, new int[]{R.attr.state_mycustom}); } else { mergeDrawableStates(states, new int[]{-R.attr.state_mycustom}); } return states; } }
- 修正Selector的匹配属性
把Selector中原来写的app:mycustom替换为自定义状态app:state_mycustom:
- 修正Selector的匹配属性
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item app:state_mycustom="false"> <!-- 对应false状态的Drawable --> </item> <item app:state_mycustom="true"> <!-- 对应true状态的Drawable --> </item> </selector>
子元素使用场景补充
如果需要在MyComponent的子View的Selector中使用这个自定义状态,只需要在子View的布局节点上添加如下配置,让子View同步父View的Drawable状态即可:
android:duplicateParentState="true"
内容的提问来源于stack exchange,提问作者LLL
相关产品推荐
相关产品推荐

