Android selector選擇器自定義屬性

Android selector選擇器自定義屬性

Android系統(tǒng)為UI的背景制定了靈活的繪制方案玻佩,drawable方式淆党。開發(fā)者可以通過各種各樣的drawable樣式來為自己的UI靈活展示各自的風(fēng)格。在selector選擇器中贮缕,系統(tǒng)提供了類似state_enables的屬性,讓組件在不同的狀態(tài)下展示不同的UI效果俺榆。

在筆者研(shi)究(yong)timessquare項(xiàng)目時(shí)感昼,發(fā)現(xiàn)selector的屬性可以自定義,瞬間像發(fā)現(xiàn)新大陸一樣罐脊,激動(dòng)得不得了定嗓。下面筆者將從中學(xué)到的東西做一點(diǎn)記錄蜕琴,以加深印象。

識別你的自定義屬性

自定義View

自定義View的目的是為了讓View擁有超出于系統(tǒng)的附加屬性宵溅。

自定義屬性

首先了解你的需求凌简,系統(tǒng)可以滿足的盡量用系統(tǒng)的,然后才選擇自定義恃逻。

例如:我需要為不同的銀行卡設(shè)定不同的背景雏搂。

實(shí)現(xiàn)方式1:定義很多個(gè)不同的shape或者使用系統(tǒng)的不同state狀態(tài)為不同的銀行卡進(jìn)行背景的定義。Perfect寇损!但是不是我的菜畔派。

實(shí)現(xiàn)方式2:直接使用自定義View的onDraw方法繪制不同的背景。Perfect润绵!但是這也不是我的菜线椰。

實(shí)現(xiàn)方式3:為selector選擇器增加額外的state屬性。Perfect尘盼!這正是我要說的憨愉!

廢話了一大推,下面開始自定義屬性卿捎。

<declare-styleable name="BankCardContainerLayout">
   <attr name="bank_card_type" format="enum">
       <enum name="red" value="1" />
       <enum name="green" value="2" />
       <enum name="blue" value="3" />
   </attr>
   <attr name="bank_card_type_red" format="boolean" />
   <attr name="bank_card_type_blue" format="boolean" />
   <attr name="bank_card_type_green" format="boolean" />
</declare-styleable>

上面的三個(gè)boolean類型的屬性配紫,都是用在selector中的,用法類似系統(tǒng)的state_enabled午阵。

使用自定義的屬性為selector添磚加瓦

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
    <item app:bank_card_type_red="true">
        <shape>
            <gradient android:angle="180" android:endColor="#e85c65" android:startColor="#e9527b" />
            <corners android:radius="0dp" />
        </shape>
    </item>
    <item app:bank_card_type_blue="true">
        <shape>
            <gradient android:angle="180" android:endColor="#41a4e5" android:startColor="#6280e0" />
            <corners android:radius="0dp" />
        </shape>
    </item>
    <item app:bank_card_type_green="true">
        <shape>
            <gradient android:angle="180" android:endColor="#1ab093" android:startColor="#0ca3ac" />
            <corners android:radius="0dp" />
        </shape>
    </item>
</selector>

在編輯selector時(shí)躺孝,引入xmlns:app="http://schemas.android.com/apk/res-auto"命名空間,以使用自定義屬性底桂。

實(shí)現(xiàn)需求


public class BankCardContainerLayout extends RelativeLayout {

    final int ext_attr[] = {
            R.attr.bank_card_type
    };

    final int ext_attr_red[] = {
            R.attr.bank_card_type_red
    };

    final int ext_attr_blue[] = {
            R.attr.bank_card_type_blue
    };

    final int ext_attr_green[] = {
            R.attr.bank_card_type_green
    };

    public static final int RED = 1;
    public static final int GREEN = 2;
    public static final int BLUE = 3;

    private int bk_type = 1;

    public BankCardContainerLayout(Context context) {
        this(context, null);
    }

    public BankCardContainerLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BankCardContainerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray array = context.obtainStyledAttributes(attrs, ext_attr);
        if (array != null) {
            setType(array.getInt(R.styleable.BankCardContainerLayout_bank_card_type, 1));
            array.recycle();
        }
    }

    /**
     * @param type {@link #RED}  {@link #GREEN}  {@link #BLUE}
     */
    public void setType(int type) {
        this.bk_type = type;
        refreshDrawableState();
    }

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        int drawableState[] = super.onCreateDrawableState(extraSpace + 1);
        switch (bk_type) {
            case RED:
                mergeDrawableStates(drawableState, ext_attr_red);
                break;
            case GREEN:
                mergeDrawableStates(drawableState, ext_attr_green);
                break;
            case BLUE:
                mergeDrawableStates(drawableState, ext_attr_blue);
                break;
        }
        return drawableState;
    }
}

解析

關(guān)鍵方法

onCreateDrawableState方法

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().

view的drawable狀態(tài)失效時(shí)植袍,通過這個(gè)方法為view創(chuàng)建新的drawable狀態(tài)。

例如:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
   <item android:state_enabled="true" drawable="@color/red"/>
   <item android:state_enabled="false" drawable="@color/green"/>
</selector>

將以上selector作為某個(gè)view的背景時(shí)籽懦,通過setEnabled方法于个,就是一種引起view的drawable狀態(tài)失效。

mergeDrawableState方法

Merge your own state values in additionalState into the base state values baseState that were returned by onCreateDrawableState(int)

將自定義state作為additionalStateonCreateDrawableState方法所返回的baseState進(jìn)行合并暮顺。

refreshDrawableState方法

Call this to force a view to update its drawable state. This will cause drawableStateChanged to be called on this view. Views that are interested in the new state should call getDrawableState.

調(diào)用此方法強(qiáng)制刷新view的drawable狀態(tài)厅篓。并且調(diào)用drawableStateChanged方法〈仿耄控件一般通過getDrawableState方法來獲取新的狀態(tài)羽氮。

通過查看View的源碼知曉,setEnabled惫恼、setSelected等一系列方法都會引起refreshDrawableState方法档押。

getDrawableState方法

Return an array of resource IDs of the drawable states representing the current state of the view.

調(diào)用流程

通過上述關(guān)鍵方法的描述可以大概了解自定義selector屬性生效過程。這里用上一個(gè)例子加以描述。

  1. 自定義的setType方法實(shí)現(xiàn)了類似setEnabled方法的功能汇荐。當(dāng)調(diào)動(dòng)改方法時(shí)洞就,通知自定義view更新drawable狀態(tài),即調(diào)用refreshDrawableState方法掀淘。
  2. refreshDrawableState方法內(nèi)部調(diào)用drawableStateChanged方法旬蟋。
  3. drawableStateChanged方法通過getDrawableState方法獲取最新的drawable狀態(tài)值。
  4. getDrawableState方法調(diào)用自定義類內(nèi)的onCreateDrawableState方法來實(shí)現(xiàn)drawable狀態(tài)的變更(通過mergeDrawableStates方法)革娄。
  5. 通過新的drawable狀態(tài)來更新view的背景倾贰。

最后

我的一枚程序員,但是英語真的很重要拦惋。沒有什么是閱讀源碼解決不了的匆浙。

2017-03-14于被窩內(nèi)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市厕妖,隨后出現(xiàn)的幾起案子首尼,更是在濱河造成了極大的恐慌,老刑警劉巖言秸,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件软能,死亡現(xiàn)場離奇詭異,居然都是意外死亡举畸,警方通過查閱死者的電腦和手機(jī)查排,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抄沮,“玉大人跋核,你說我怎么就攤上這事∨崖颍” “怎么了砂代?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長聪全。 經(jīng)常有香客問我泊藕,道長辅辩,這世上最難降的妖魔是什么难礼? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮玫锋,結(jié)果婚禮上蛾茉,老公的妹妹穿的比我還像新娘。我一直安慰自己撩鹿,他們只是感情好谦炬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般键思。 火紅的嫁衣襯著肌膚如雪础爬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天吼鳞,我揣著相機(jī)與錄音看蚜,去河邊找鬼。 笑死赔桌,一個(gè)胖子當(dāng)著我的面吹牛供炎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播疾党,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼音诫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了雪位?” 一聲冷哼從身側(cè)響起竭钝,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎雹洗,沒想到半個(gè)月后蜓氨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡队伟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年穴吹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗜侮。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡港令,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出锈颗,到底是詐尸還是另有隱情顷霹,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布击吱,位于F島的核電站淋淀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏覆醇。R本人自食惡果不足惜朵纷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望永脓。 院中可真熱鬧袍辞,春花似錦、人聲如沸常摧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谎懦,卻和暖如春肚豺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背界拦。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工详炬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人寞奸。 一個(gè)月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓呛谜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親枪萄。 傳聞我的和親對象是個(gè)殘疾皇子隐岛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,185評論 25 707
  • 你是否曾抱怨過產(chǎn)品經(jīng)理,為什么一個(gè)app里面按鈕正常/按下狀態(tài)顏色不統(tǒng)一起來瓷翻?你是否曾埋怨過UI聚凹,為什么不同地方輸...
    chuwe1閱讀 2,708評論 2 28
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)齐帚,斷路器妒牙,智...
    卡卡羅2017閱讀 134,672評論 18 139
  • 1、View的幾種不同狀態(tài)屬性2对妄、如何根據(jù)不同狀態(tài)去切換我們的背景圖片湘今。 開篇介紹:Android背景選擇器sel...
    瀚海江天閱讀 6,786評論 0 1
  • 123tsg.com (一)有效行為 行為者:123圖書館辦公室主任 地點(diǎn):辦公室 時(shí)間:4月18號 觀察者:12...
    啊啊丫頭閱讀 267評論 0 0