58

I have a button and I want it to have different background when I set:

android:enabled="false"

Here's resource file for background:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="false"
          android:drawable="@drawable/bttn_orange_normal" /> <!-- pressed -->
    <item android:state_pressed="true"
          android:drawable="@drawable/bttn_orange_selected" /> <!-- focused -->
    <item android:state_enabled="false" android:drawable="@drawable/bttn_grey_disabled"/>
    <item android:state_enabled="true" android:drawable="@drawable/bttn_orange_normal"/>
</selector>

But button still has normal background when it is disabled. What am I missing?

  • 2
    try to add at first item section android:state_enabled="true" – Georgy Gobozov Dec 26 '12 at 15:56
  • pressed false is not pressed. also, not specifying a state doesn't mean false, either. it means it is not considered. so, your rule here means any time a button is not pressed, it has the normal bg. – njzk2 Dec 26 '12 at 16:14
  • You must delete the **android:state_enabled="true"** of last item, that way all other statuses will have the **@drawable/bttn_orange_normal**. Once your button is disbled it'll get the **@drawable/bttn_grey_disabled** in the right place. Also you must remove the line that has the **android:state_pressed="false"** because it will override the definition of ***android:state_enabled="false"*** – alexscmar Dec 21 '15 at 10:32

3 Answers3

161

Put this line :

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

as first item (it must be first item, otherwise it will not work) of the selector tag.

Final :

<selector xmlns:android="http://schemas.android.com/apk/res/android">
            <item android:state_enabled="false" android:drawable="@drawable/bttn_grey_disabled"/>
            <item android:state_pressed="false"
              android:drawable="@drawable/bttn_orange_normal" /> <!-- pressed -->
            <item android:state_pressed="true"
              android:drawable="@drawable/bttn_orange_selected" /> <!-- focused -->
            <item android:state_enabled="true" android:drawable="@drawable/bttn_orange_normal"/> <!-- idle state -->
</selector>
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Vincent Ducastel
  • 10,121
  • 2
  • 17
  • 11
  • 22
    @Estel I don't think it is a crazy stupid rule. Think about selector as a switch case. Think about each item within selector as a "case" statement with "break" at the end. The first item is: `` which is true, the normal background will be set. – Singed May 19 '15 at 09:01
41

Vincent Ducastel's answer is correct, however it does not describe why the solution works.

When Android traverses the list of available items, it traverses the list from top to bottom, in each case evaluating whether the current state of the view matches the states defined for each item. It then selects the first item that matches the conditions and ignores the rest.

This is why you should always provide a default item at the bottom of the list and also provides a means of displaying complex selection conditions. For example if you wanted to have a special pressed state when the item is disabled, you would define the following items:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    ...
    <item android:state_enabled="false" android:state_pressed="false" android:drawable="@drawable/btn_grey_disabled"/>
    <item android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/btn_white_disabled_selected"/>
    ...
</selector>
TheIT
  • 11,919
  • 4
  • 64
  • 56
0

Added example of Active, Default and Disable State

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

    <!--Disable-->
    <item android:drawable="@drawable/ic_button_disable"
        android:state_enabled="false" 
        android:state_pressed="false" />

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


    <!--Default-->
    <item android:drawable="@drawable/ic_button_default"  
        android:state_pressed="false"    
        android:state_selected="false" />

    <item android:drawable="@drawable/ic_button_default_touch" 
        android:state_pressed="true" 
        android:state_selected="false"  />


    <!--Active-->
    <item android:drawable="@drawable/ic_button_active" 
        android:state_enabled="true" 
        android:state_selected="true" 
        android:state_pressed="false" />

    <item android:drawable="@drawable/ic_button_active_touch" 
        android:state_enabled="true" 
        android:state_pressed="true" 
        android:state_selected="true" />
</selector>
Hitesh Sahu
  • 41,955
  • 17
  • 205
  • 154