在编写一个自定义控件时候,遇到一个通过自定义属性切换背景颜色需求,一开始我通过两个自定义属性来来设置不同状态下的颜色,然后通过代码逻辑进程选择切换,后来久想能不能通过selector,设置类似android:state_checked、android:state_enabled这类属性一样进行设置,通过测试,最后总算是实现。下面对一些步骤做一些记录和整理。
1 首先当然是需要对这些自定义属性进行创建声明,在values/attrs.xml中进行自定义属性命名如下:
自定义属性定义2 我们在自定义控件中去接收对应的属性值并实现对应逻辑
在自定义控件的构造方法中获取对应的属性值,因为其中csl_next_bg_color为颜色值,可能是两中状态,所以我们用ColorStateList对象进行接收。
获取属性值 因为是通过next_enable属性进行设置获取,所以我们需要定义两个状态的数组,其中加负号为false状态,至于定义数组是因为我们从ColorStateList中获取对应颜色时候需要用到数组。其中要注意的是使用R.attr.id而不是向上面获取属性时候使用R.styleable.id,一开始没注意使用错了获取颜色时候老是不对(囧。。。)
然后我们在自定义控件中重写onCreateDrawableState方法来创建对应不同状态的数组。
其中下面代码中“+1”表示添加一种自定义属性状态,如何设置多种就加几。然后通过类型状态创选取上面定义的数组进行初始化数组。
@Override
protected int[] onCreateDrawableState(int extraSpace) {
int drawableState[] = super.onCreateDrawableState(extraSpace + 1);
if (next_enable) {
mergeDrawableStates(drawableState, NEXT_STATE_ENABLE);
} else {
mergeDrawableStates(drawableState, NEXT_STATE_DISABLE);
}
return drawableState;
}
接着我们就可以通过ColorStateList的getColorForState方法获取当前状态下的具体值了。其中getDrawableState()方法为父类方法,会调用我们重写的onCreateDrawableState的方法进行状态数组的获取。
private void upNextEnable() {
if (csl_next_bg_color != null) {
next_bg_color = csl_next_bg_color.getColorForState(getDrawableState(), 0);
} else {
}
}
最后在状态切换api中,我们需要重新刷新属性值并刷新界面。其中refreshDrawableState方法是父类方法,如果不调用会造成onCreateDrawableState方法中的状态数组没有被清理,从而造成数据错误。
public void setNextEnable(boolean enable) {
if (next_enable != enable) {
next_enable = enable;
refreshDrawableState();
upNextEnable();
invalidate();
}
}
3 最后我们只要在使用自定义控件时候编写selector设置颜色及在自定义控件引用时候进行设置就可以了
bg_select_color_is.xml具体实现可以看git:https://gitee.com/zhengdd/MyWidget
网友评论