背景
在android 的实际开发中,我们经常会遇到这样的情况:需要根据不同逻辑判断来显示,icon/color,将判断逻辑加在adapter的getview方法中,总感觉不符合mvc模式,也影响代码的阅读。有人会说,可以使用类似于,选择器的一种东东来处理,这个思路是对了,但是还缺一点,下面我们先来看看缺点什么!
1.常规的checkbox等,可点击控件需要,监听控件的一个状态:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="#FFF" />
<item android:state_focused="true" android:color="#FFF" />
<item android:state_pressed="true" android:color="#FFF" />
<item android:color="#000" />
</selector>
如同上面这段代码,监听state_selected、state_pressed的变化,然后响应的刷新状态,来改变控件的显示,那么问题来了:button是怎么做到的呢。我们来看看checkbox的源码:
public void setChecked(boolean checked) {
//如果和当前状态相反
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();//刷新控DrawableStatasl,调次方法会,调用下面的方法;
//此处省略代...
}
监听的属性
private static final int[] CHECKED_STATE_SET = {
R.attr.state_checked
};
@Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);//多状态监听,+1(),生成drawables的数组;
if (isChecked()) {
//根据监听的属性:CHECKED_STATE_SET,将结果drawables数组复制到drawableState中;注意:CHECKED_STATE_SET属性,如果我们定义一个属性,并监听此属性值变化,就可以拿到对应drawables数组,这是接下来自定义的关键
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
2.自定义控件时:
a.监听属性
b.根据逻辑判断给属性赋值
c.刷新drawables状态
代码中需要添加,和实现的方法
private static final int[] SEFT_DEFINATION_ATRR= {
R.attr.self_defination_atrr
};
public void setAtrrValue(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
//此处省略代...
}
@Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, SEFT_DEFINATION_ATRR);
}
return drawableState;
}
3.根绝监听属性设置selector
a.申明自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="checkBoxStatus">
<attr name="check_box_status" format="boolean" />
</declare-styleable>
</resources>
b.编辑选择器
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
//注意自定义属性命名空间 xmlns:yl="http://schemas.android.com/apk/res/com.example.testcheckbox">
<item android:drawable="@drawable/jc_box_false" yl:**check_box_status**="false"/>//加粗部分即为监听的属性
<item android:drawable="@drawable/jc_box_true" yl:check_box_status="true"/>
</selector>
c.设置背景
<com.example.testcheckbox.TestView
android:layout_gravity="center"
android:id="@+id/testView1"
**android:background="@drawable/back_groud"**
android:layout_width="25dp"
android:layout_height="30dp" />
4.结果:
我们在代码中,只要根据逻辑判断设置:
testView.setCheckBoxChecked(true);
就会有下面的结果:
getListView().setAdapter(new ArrayAdapter<Object>(getApplicationContext(), 0, objs) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view = View.inflate(getApplicationContext(), R.layout.item, null);
TestView testView = (TestView) view.findViewById(R.id.testView1);
if (position % 5 == 0) {
testView.setCheckBoxChecked(true);
}
return view;
}
});
代码也很干净,少了很多逻辑判断,有么有?
本篇博文参考了:大神鸿洋的博文drawable 的一些少为人知的用法,本博是在自己理解的基础上,结合实际开发的体会;