您的位置:首页 > 其它

如何自定义`Selector`状态选择器

2016-02-02 12:51 423 查看

为撒要使用
Selector
状态选择器?!

Selector
状态选择器的使用肯定是超级多的。有时候自定义某个控件,也需要对BackGround等作统一的状态修改,这时候要是可以响应状态变化使用到状态选择器而不是自己去手动的setBackGround那才是极好的啊!!

其实一开始我也不知道这个是怎么去触发相关的状态更改的。但是这个肯定是定义在View里面的,然后,肯定是有一个触发事件,(一般就是点击事件啦),然后,肯定是需要通知View去重新绘制的。

Android中就能找到的相关代码!

@Override
public int[] onCreateDrawableState(int extraSpace) {
return super.onCreateDrawableState(extraSpace);
}


Generate the new Drawable state for this view. This is called by the view system when the cached Drawable state is determined to be invalid. To retrieve the current state, you should use
getDrawableState
.

找了找,在TextView中,有如下的定义:

这是在View中
setEnabled
的方法。

@RemotableViewMethod
public void setEnabled(boolean enabled) {
if (enabled == isEnabled()) return;

setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);

/*
* The View most likely has to change its appearance, so refresh
* the drawable state.
*/
refreshDrawableState();

// Invalidate too, since the default behavior for views is to be
// be drawn at 50% alpha rather than to change the drawable.
invalidate(true);

if (!enabled) {
cancelPendingInputEvents();
}
}


在TextView中的
onCreateDrawableState
的方法。

@Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState;

if (mSingleLine) {
drawableState = super.onCreateDrawableState(extraSpace);
} else {
drawableState = super.onCreateDrawableState(extraSpace + 1);
mergeDrawableStates(drawableState, MULTILINE_STATE_SET);
}


这里这个
MULTILINE_STATE_SET
是酱紫滴。

// New state used to change background based on whether this TextView is multiline.
private static final int[] MULTILINE_STATE_SET = { R.attr.state_multiline };


在View中对应的
mergeDrawableStates
的方法。

protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
final int N = baseState.length;
int i = N - 1;
while (i >= 0 && baseState[i] == 0) {
i--;
}
System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
return baseState;
}


看到这里,其实就可以明白,我们要做的就是把我们定义的状态给它默认添加进去,然后还要加入一个条件,就是状态改变的触发条件。

自己做一个!

定义个
STATE_FOCUSED
状态

private static final int[] STATE_FOCUSED = new int[]{android.R.attr.state_focused};

实时添加这个状态,复写
onCreateDrawableState
的方法,根据情况决定是否添加。

@Override
public int[] onCreateDrawableState(int extraSpace) {
int[] states = super.onCreateDrawableState(extraSpace + 1);
if (pressed) {
mergeDrawableStates(states, STATE_FOCUSED);
}
return states;
}


决定触发条件。

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
refreshState(true);
break;

case MotionEvent.ACTION_UP:
refreshState(false);
break;
default:
break;
}
return true;
}

private void refreshState(boolean state) {
if (pressed != state) {
pressed = state;
refreshDrawableState();
}
}


这里就是那个press状态的修改的地方。在
refreshState
的方法中进行状态的修改,如果的确是修改了,那么就调用
refreshDrawableState
的方法,这个方法一定要调用,不然不重画,你设置的状态压根不起作用。


最后的效果是酱紫滴!!就是最右边那个
IndexBar
啦!!! 相关源码和Demo下载请移步 —>我的GitHub<—

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  控件 Selector