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最好都是'自定義'過的, 哪怕初始只是個簡單的繼承類, 等到'未來'需要擴展時, 你就懂了, 嘿嘿...