主要是有业务需求的前提下,尽量不要做可以避免的硬编码,以防后续更改时挖下巨坑。 经常会在需求上遇到有对一个view(ViewGroup)做状态变更,ui状态改变 如果是单个View,是可以考虑直接使用系统控件去实现效果
例如
RadioButton
RadioGroup
CheckedTextView
...
在满足比较常见的效果外,我们还会考虑如果是更为复杂的组合控件,甚至可能要考虑多种状态 CheckedTextView 能不能再添加一种新的状态呢,这确实是一个非常有意思的事情呢
先看下有哪些类型的属性是支持添加新状态的。 哈哈,皮了一下。 其实是绝大多数类型的属性都是支持的
android:background
android:text
android:textColor
...
以上对应系统定义的属性
android.R.attr.background
...
例如TextView 本来是不支持state_checked 状态,添加了新状态后就是CheckedTextView
这个时候不得不去看下CheckedTextView 是如何添加的state_checked状态了
刚打开就看到这么一行代码,好像就是我们要添加的新状态(state_checked)

那么继续往下看,是哪里使用到这里的状态
这里大致解释一下,
extraSpace+1 是表示添加一种状态,个人觉得,是不是用上边的set.size()替换更合适呢,当然在这里明显知道是只添加一种状态,感觉还可以接受啦。
mergeDrawableStatus是View的方法,先看下怎么解释这个方法的
这个很好理解,就是在原来的基础上添加新的状态,并且最终添加后的状态是在
onCreateDrawableState方法的返回对象中体现
说到这里,基本就是一些核心方法了,
接下来就是处理对状态样式的处理

上图为一个ViewGroup在处理state_checked状态时的操作,也需要对子View担当起相应的义务哦~。
如果是CheckedTextView相对TextView添加的state_checked状态,反而没那么复杂.如下

public class CheckableLayout extends LinearLayout implements Checkable {
private static
@StyleableRes
int[] sys_attrs = {
android.R.attr.background
};
private static final int[] STATE_ADD = {
android.R.attr.state_checked
};
private boolean mChecked;
private Drawable mDrawable;
private int[] mDefaultState;
public CheckableLayout(Context context) {
this(context, null);
}
public CheckableLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CheckableLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs, sys_attrs);
mDrawable = typedArray.getDrawable(0);
if (mDrawable instanceof StateListDrawable) {
StateListDrawable stateListDrawable = (StateListDrawable) mDrawable;
mDefaultState = stateListDrawable.getState();
}
typedArray.recycle();
}
@Override
protected int[] onCreateDrawableState(int extraSpace) {
int[] state = super.onCreateDrawableState(extraSpace + 1);
if (mChecked) {
mergeDrawableStates(state, STATE_ADD);
}
return state;
}
@Override
public void setChecked(boolean checked) {
if (!isEnabled()) {
return;
}
if (mChecked == checked) {
return;
}
mChecked = checked;
refreshDrawableState();
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
if (view instanceof Checkable) {
Checkable checkable = (Checkable) view;
checkable.setChecked(mChecked);
}
}
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
view.setEnabled(enabled);
}
}
@Override
public boolean isChecked() {
return mChecked;
}
@Override
public void toggle() {
setChecked(!mChecked);
}
}

