如何自定义`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<—
![](https://raw.githubusercontent.com/lovejjfg/IndexMasterDemo/master/index.gif)
相关文章推荐
- flex 控件的重要属性
- Delphi控件ListView的属性及使用方法详解
- web下载的ActiveX控件自动更新
- WinForm实现按名称递归查找控件的方法
- C#中父窗口和子窗口之间控件互操作实例
- Android编程之Button控件用法实例分析
- Android控件之CheckBox、RadioButton用法实例分析
- MFC中动态创建控件以及事件响应实现方法
- WinForm自定义函数FindControl实现按名称查找控件
- Android控件之ProgressBar用法实例分析
- WinForm拖拽控件生成副本的解决方法
- ASP.NET动态添加用户控件的方法
- ASP.NET的HtmlForm控件学习及Post与Get的区别概述
- WinForm实现移除控件某个事件的方法
- C#分屏控件用法实例
- 可以浮动某个物体的jquery控件用法实例
- jQuery操作基本控件方法实例分析
- jQuery操作表单常用控件方法小结
- C#的winform控件命名规范
- Jquery给基本控件的取值、赋值示例