Android CheckBox setButtonDrawable(null) 在 4.x 版本中無(wú)效

當(dāng)我們需要只顯示 CheckBox 的文字抖拴,而不顯示按鈕的時(shí)候凡恍,通常在 XML 文件中設(shè)置 CheckBox 的 android:button="@null"。

當(dāng)我們自定義 CheckBox 并希望在代碼中控制按鈕不顯示的時(shí)候,可以 setButtonDrawable(null) 來(lái)達(dá)到效果狈癞。

但是有一個(gè)問(wèn)題履羞,setButtonDrawable(null) 在 4.x 中是沒(méi)有效果的峦萎,從 5.0 開始才有效果。

為了調(diào)查為什么 4.x 沒(méi)有效果忆首,我們來(lái)分別看看 4.4 和 5.0 的源碼爱榔,到底 setButtonDrawable 方法有什么不同。

關(guān)于查看 Android 各版本的源碼推薦兩個(gè)網(wǎng)站:
GrepCode
AndroidXRef

先來(lái)看 4.4 的源碼糙及,其實(shí) setButtonDrawable 方法在 CheckBox 的父類 CompoundButton 中详幽。

   /**
     * Set the background to a given Drawable
     *
     * @param d The Drawable to use as the background
     */
    public void setButtonDrawable(Drawable d) {
        if (d != null) {
            if (mButtonDrawable != null) {
                mButtonDrawable.setCallback(null);
                unscheduleDrawable(mButtonDrawable);
            }
            d.setCallback(this);
            d.setVisible(getVisibility() == VISIBLE, false);
            mButtonDrawable = d;
            setMinHeight(mButtonDrawable.getIntrinsicHeight());
        }

        refreshDrawableState();
   }

可以看到如果 Drawable 為 null,就直接跳過(guò)去了,沒(méi)有任何效果唇聘!

再來(lái)看看 5.0 中的源碼

    public void More ...setButtonDrawable(Drawable d) {
        if (mButtonDrawable != d) {
            if (mButtonDrawable != null) {
                mButtonDrawable.setCallback(null);
                unscheduleDrawable(mButtonDrawable);
            }

            mButtonDrawable = d;

            if (d != null) {
                d.setCallback(this);
                d.setLayoutDirection(getLayoutDirection());
                if (d.isStateful()) {
                    d.setState(getDrawableState());
                }
                d.setVisible(getVisibility() == VISIBLE, false);
                setMinHeight(d.getIntrinsicHeight());
                applyButtonTint();
            }
        }
    }

可以看到并不是判斷為不為 null版姑,而是判斷和之前的一樣不一樣,CheckBox 默認(rèn)是有按鈕的迟郎,所以默認(rèn) mButtonDrawable 是不為 null 的剥险,所以判斷成立,mButtonDrawable 被賦為 null宪肖。

也許你會(huì)問(wèn)表制,為什么 android:button="@null" 不管是 4.x 還是 5.0 之后都是有效果的呢?那我們就得看看構(gòu)造方法初始化的源碼了

     public More ...CompoundButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, com.android.internal.R.styleable.CompoundButton, defStyleAttr, defStyleRes);
 
         final Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button);
         if (d != null) {
             setButtonDrawable(d);
         }
         ......
         ......
    }

可以看到匈庭,如果傳進(jìn)來(lái)的 Drawable 不為 null夫凸,才設(shè)置初始按鈕。這部分代碼 4.x 和 5.0 以后都一樣阱持,所以 android:button="@null" 是不受版本影響的夭拌。

至于初始按鈕的樣式可以看 CheckBox 中的構(gòu)造方法的源碼

public CheckBox(Context context, AttributeSet attrs) {
    this(context, attrs, com.android.internal.R.attr.checkboxStyle);
}

可以看到初始樣式是 com.android.internal.R.attr.checkboxStyle。
com.android.internal....可以到 android / frameworks / base / core / res / res / values 下面去找衷咽。
checkboxStyle 在 themes.xml 中

<item name="checkboxStyle">@style/Widget.CompoundButton.CheckBox</item>

繼續(xù)看 style.xml 中的 Widget.CompoundButton.CheckBox

    <style name="Widget.CompoundButton.CheckBox">
        <item name="button">?attr/listChoiceIndicatorMultiple</item>
    </style>

listChoiceIndicatorMultiple 還是在 themes.xml 中

<item name="listChoiceIndicatorMultiple">@drawable/btn_check</item>

繼續(xù)到 android / frameworks / base / core / res / res / drawable 下去找 btn_check.xml

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

    <!-- Enabled states -->
        
    <item android:state_checked="true" android:state_window_focused="false"
          android:state_enabled="true"
          android:drawable="@drawable/btn_check_on" />
    <item android:state_checked="false" android:state_window_focused="false"
          android:state_enabled="true"
          android:drawable="@drawable/btn_check_off" />

    <item android:state_checked="true" android:state_pressed="true"
          android:state_enabled="true"
          android:drawable="@drawable/btn_check_on_pressed" />
    <item android:state_checked="false" android:state_pressed="true"
          android:state_enabled="true"
          android:drawable="@drawable/btn_check_off_pressed" />

    <item android:state_checked="true" android:state_focused="true"
          android:state_enabled="true"
          android:drawable="@drawable/btn_check_on_selected" />
    <item android:state_checked="false" android:state_focused="true"
          android:state_enabled="true"
          android:drawable="@drawable/btn_check_off_selected" />

    <item android:state_checked="false"
          android:state_enabled="true"
          android:drawable="@drawable/btn_check_off" />
    <item android:state_checked="true"
          android:state_enabled="true"
          android:drawable="@drawable/btn_check_on" />


    <!-- Disabled states -->

    <item android:state_checked="true" android:state_window_focused="false"
          android:drawable="@drawable/btn_check_on_disable" />
    <item android:state_checked="false" android:state_window_focused="false"
          android:drawable="@drawable/btn_check_off_disable" />

    <item android:state_checked="true" android:state_focused="true"
          android:drawable="@drawable/btn_check_on_disable_focused" />
    <item android:state_checked="false" android:state_focused="true"
          android:drawable="@drawable/btn_check_off_disable_focused" />

    <item android:state_checked="false" android:drawable="@drawable/btn_check_off_disable" />
    <item android:state_checked="true" android:drawable="@drawable/btn_check_on_disable" />

</selector>

到這邊鸽扁,我們就找到了 CheckBox 默認(rèn)的按鈕效果。

等等镶骗,說(shuō)了這么多桶现,到底 setButtonDrawable(null) 在 4.x 版本中無(wú)效的問(wèn)題怎么解決呢?辦法很簡(jiǎn)單鼎姊,setButtonDrawable(new StateListDrawable()) 即可骡和!

最后,不僅僅 CheckBox相寇,所有繼承自 CompoundButton 的控件都有這個(gè)問(wèn)題慰于,可以看看 CompoundButton 有哪些子控件

如圖,RadioButton唤衫,Switch 等等的控件都是繼承自 CompoundButton 的婆赠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市佳励,隨后出現(xiàn)的幾起案子休里,更是在濱河造成了極大的恐慌,老刑警劉巖赃承,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妙黍,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡瞧剖,警方通過(guò)查閱死者的電腦和手機(jī)废境,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人噩凹,你說(shuō)我怎么就攤上這事巴元。” “怎么了驮宴?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵逮刨,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我堵泽,道長(zhǎng)修己,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任迎罗,我火速辦了婚禮睬愤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纹安。我一直安慰自己尤辱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布厢岂。 她就那樣靜靜地躺著光督,像睡著了一般。 火紅的嫁衣襯著肌膚如雪塔粒。 梳的紋絲不亂的頭發(fā)上结借,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音卒茬,去河邊找鬼船老。 笑死,一個(gè)胖子當(dāng)著我的面吹牛圃酵,可吹牛的內(nèi)容都是我干的柳畔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼辜昵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼荸镊!你這毒婦竟也來(lái)了咽斧?” 一聲冷哼從身側(cè)響起堪置,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎张惹,沒(méi)想到半個(gè)月后舀锨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宛逗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年坎匿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡替蔬,死狀恐怖告私,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情承桥,我是刑警寧澤驻粟,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站凶异,受9級(jí)特大地震影響蜀撑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剩彬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一酷麦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧喉恋,春花似錦沃饶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至苔悦,卻和暖如春轩褐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背玖详。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工把介, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蟋座。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓拗踢,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親向臀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子巢墅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

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