Android中的常用View, 如TextView, Button等, 都有state概念 -- state_pressed, state_selected, state_enabled等等, 这些状态都是boolean类型的变量, 可以通过其set/get方法读取或者设置这些状态.
状态的概念在其他平台或者GUI库中都是存在的, 因为这些是View的基本属性, 但Android中将其与View的Color/Drawable属性捆绑起来的做法极大地简化了UI中维护状态变化与其它属性变化的操作. 具体可参看如下Android文档 --
ColorStateList.
Android的TextView自身提供了很多state, 比如state_selected. 在实际使用中, 我们可以通过此属性, 结合selector一起来实现某些需求 -- 同一字符串通过二元的颜色来标明状况的不同, 如一封邮件是否读取过等等. 但如果此时使用state_selected会引起个问题 -- 如果此时真的'选中'了当前的TextView, 就会引起不必要的'混乱'. 这是因为系统的'选中', 如使用方向键选中, 和代码中的setSelected()是有相同效果的. 此时有何感想? 是不是真心觉得state不够用呢? 因此 --
今天咱们聊个好玩的 -- 自己定制state!
基本思想很简单 -- state是View的属性项, 那么为了定制state, 只需为View创建相应的新的state属性项, 然后封装个能处理此属性的TextView类即可.
1. 定义新的state属性项
在attrs.xml中(其实什么xml都可以, 只要放到res下能看到就好)定义新的state属性.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyCustomTextView">
<attr name="state_unread" format="boolean" />
</declare-styleable>
</resources>
2. 创建新的TextView类
继承与TextView类, 创建自定义TextView类以处理新的state属性.
public class MyCustomTextView
extends TextView {
private static final int[] STATE_UNREAD = { R.attr.state_unread };
private boolean mIsUnread =
false;
public void setUnreadState(
boolean isUnread) {
mIsUnread = isUnread;
refreshDrawableState();
}
@Override
protected int[] onCreateDrawableState(
int extraSpace) {
final int[] state =
super.onCreateDrawableState(extraSpace + 1);
if (mIsUnread) {
mergeDrawableStates(state, STATE_UNREAD);
}
return state;
}
}
a. 定义状态属性项 --
private static final int[] STATE_UNREAD = { R.attr.state_unread };
b. 定义状态变量 --
private boolean mIsUnread = false;
c. 新属性set函数 -- setUnreadState()
d. 添加新属性支持 -- 重载onCreateDrawableState()
e. 搞定
3. 在selector添加新属性
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto" >
<item custom:state_unread="true" android:color="@color/theme_1" />
<item android:state_selected="true" android:color="@color/theme_2" />
<item android:color="@color/theme_0" />
</selector>
因为这个state_unread属性是自定义的, 所以要注意添加其ns, 不然会有编译错误 -- 无法找到xxxx定义.
Andoird的View提供了灵活的定制功能, 除了state可以如上自定义外, 其它的属性, 比如Font什么的, 都是可以通过此方式实现自定义属性添加的. 反过来, 为了'漂亮'的UI, app所使用的View最好都是'自定义'过的, 哪怕初始只是个简单的继承类, 等到'未来'需要扩展时, 你就懂了, 嘿嘿...