StateListDrawable源碼詳解

StateListDrawable源碼詳解

背景

在開發(fā)過程中我們的按鈕有時(shí)候會(huì)有點(diǎn)擊和抬起用到不同的背景效果康二,一般我們是用selector.xml來實(shí)現(xiàn)的,那么android是如何解析這個(gè)xml文件的呢苍在?

xml形式

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:drawable="@drawable/button_press"
        android:state_enabled="true"
        android:state_pressed="true" />

    <item
        android:drawable="@drawable/button_press"
        android:state_enabled="false" />

    <item
        android:drawable="@drawable/button_press" />

</selector>

然后button通過 background去設(shè)置。

StateListDrawable源碼分析

selector.xml會(huì)被解析成一個(gè)StateListDrawable對象,然后進(jìn)行解析。
先看一下StateListDrawable類圖灭忠。

stateListDrawable.png

StateListDrawable繼承DrawableContainer,里面有一個(gè)StateListState對象座硕,而在StateListState里面有一個(gè)mStateSets[][] 的二維數(shù)組弛作,StateListState有繼承于DrawableContainer中DrawableContainerState類,里面有一個(gè) Drawable[] mDrawables华匾。
當(dāng)解析第一個(gè)item的時(shí)候映琳,把一維數(shù)組stateSet 存在mStateSets的第0個(gè)位置,把drawable對應(yīng)的資源存在mDrawables的第0個(gè)位置蜘拉,解析第2個(gè)item的時(shí)候萨西,把stateSet和drawable 存放mStateSets,mDrawables的第1位置旭旭,如此循環(huán)谎脯,直到解析完成。

看一下其中的源代碼:

StateListDrawable里有一個(gè)addState的方法:

/**
     * Add a new image/string ID to the set of images.
     *
     * @param stateSet - An array of resource Ids to associate with the image.
     *                 Switch to this image by calling setState().
     * @param drawable -The image to show.
     */
    public void addState(int[] stateSet, Drawable drawable) {
        if (drawable != null) {
            //將stateSet和drawable 保存起來
            mStateListState.addStateSet(stateSet, drawable);
            // in case the new state matches our current state...
            onStateChange(getState());
        }
    }

StateListState中的addStateSet:

    int addStateSet(int[] stateSet, Drawable drawable) {
        //調(diào)用DrawableContainerState 的addChild()
        final int pos = addChild(drawable);
        mStateSets[pos] = stateSet;
        return pos;
    }
    

StateListState 繼承 DrawableContainerState 直接調(diào)用父類的addChild:

/**
         * Adds the drawable to the end of the list of contained drawables.
         *
         * @param dr the drawable to add
         * @return the position of the drawable within the container
         */
        public final int addChild(Drawable dr) {
            final int pos = mNumChildren;
            if (pos >= mDrawables.length) {
                growArray(pos, pos+10);
            }

            dr.mutate();
            dr.setVisible(false, true);
            dr.setCallback(mOwner);

            mDrawables[pos] = dr;
            mNumChildren++;
            mChildrenChangingConfigurations |= dr.getChangingConfigurations();
            mCheckedStateful = false;
            mCheckedOpacity = false;

            mConstantPadding = null;
            mCheckedPadding = false;
            mCheckedConstantSize = false;
            mCheckedConstantState = false;

            return pos;
        }

代碼實(shí)現(xiàn)xml功能

分析了解析過程后持寄,其中selector.xml里可以直接用代碼實(shí)現(xiàn)源梭,比如在自定義View的時(shí)候就可以用到。

StateListDrawable stateListDrawable = new StateListDrawable();

        //注意該處的順序稍味,只要有一個(gè)狀態(tài)與之相配废麻,背景就會(huì)被換掉
        //所以不要把大范圍放在前面了,如果sd.addState(new[]{},normal)放在第一個(gè)的話模庐,就沒有什么效果了
        stateListDrawable.addState(new int[]{android.R.attr.state_pressed, android.R.attr.state_enabled}, getDrawable(android.R.attr.state_pressed));
        stateListDrawable.addState(new int[]{-android.R.attr.state_enabled}, getDrawable(-android.R.attr.state_enabled));
        //沒有任何狀態(tài)時(shí)顯示的圖片烛愧,就設(shè)置空集合,默認(rèn)狀態(tài)
        stateListDrawable.addState(new int[]{}, getDrawable(android.R.attr.state_enabled));

其中“-”表示對應(yīng)的屬性為false赖欣。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末屑彻,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子顶吮,更是在濱河造成了極大的恐慌社牲,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悴了,死亡現(xiàn)場離奇詭異搏恤,居然都是意外死亡违寿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進(jìn)店門熟空,熙熙樓的掌柜王于貴愁眉苦臉地迎上來藤巢,“玉大人,你說我怎么就攤上這事息罗〉嘀洌” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵迈喉,是天一觀的道長绍刮。 經(jīng)常有香客問我,道長挨摸,這世上最難降的妖魔是什么孩革? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮得运,結(jié)果婚禮上膝蜈,老公的妹妹穿的比我還像新娘。我一直安慰自己熔掺,他們只是感情好饱搏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著瞬女,像睡著了一般窍帝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上诽偷,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天坤学,我揣著相機(jī)與錄音,去河邊找鬼报慕。 笑死深浮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的眠冈。 我是一名探鬼主播飞苇,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蜗顽!你這毒婦竟也來了布卡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤雇盖,失蹤者是張志新(化名)和其女友劉穎忿等,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體崔挖,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贸街,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年庵寞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片薛匪。...
    茶點(diǎn)故事閱讀 40,146評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡捐川,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出逸尖,到底是詐尸還是另有隱情古沥,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布冷溶,位于F島的核電站渐白,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏逞频。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一栋齿、第九天 我趴在偏房一處隱蔽的房頂上張望苗胀。 院中可真熱鬧,春花似錦瓦堵、人聲如沸基协。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽澜驮。三九已至,卻和暖如春惋鸥,著一層夾襖步出監(jiān)牢的瞬間杂穷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工卦绣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留耐量,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓滤港,卻偏偏與公主長得像廊蜒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子溅漾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評論 2 356

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,190評論 25 707
  • 有時(shí)候覺得好累山叮,有一個(gè)怎么都不知道過日子的哥哥,總是讓我覺得日子在慢慢好起來的時(shí)候硬生生把我拖回到他的現(xiàn)實(shí)中添履。和媽...
    小阿懵閱讀 268評論 0 0
  • 不管怎樣都不做讓自己后悔的事 糟糕的日子過完了就都是好運(yùn) 我的世界太平靜了只有我一個(gè)人 太久了 久的忘了怎么去羨慕...
    廣平王妃閱讀 339評論 0 0
  • 妮寶屁倔,明天就是你的生日會(huì),畫畫課一結(jié)束缝龄,我們就開啟了愉快的購物之旅汰现,提前開心了一天挂谍。買了好多小玩意,還吃了漢堡瞎饲,一...
    恩企媽媽閱讀 142評論 0 0