100

I'm attempting to override the default ToggleButton appearance. Here's the XML that defines the ToggleButton:

<ToggleButton android:id="@+id/FollowAndCenterButton"
        android:layout_width="30px"
        android:layout_height="30px"
        android:textOn="" android:textOff="" android:layout_alignParentLeft="true"
        android:layout_marginLeft="5px"
        android:layout_marginTop="5px" android:background="@drawable/locate_me"/>

Now, we have two 30 x 30 icons we want to use for the clicked/non-clicked states. Right now we have code that programmatically changes the background icon depending on the state:

centeredOnLocation.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            if (centeredOnLocation.isChecked()) {
                centeredOnLocation.setBackgroundDrawable(getResources().getDrawable(R.drawable.locate_me_on));
            } else {
                centeredOnLocation.setBackgroundDrawable(getResources().getDrawable(R.drawable.locate_me));
            }
        }
});

Obviously I'm looking for a better way to do this. I've tried to make a selector for the background image, which would automatically switch between the states:

 <selector xmlns:android="http://schemas.android.com/apk/res/android">
 <item android:drawable="@drawable/locate_me" /> <!-- default -->
 <item android:state_checked="true"
       android:drawable="@drawable/locate_me_on" /> <!-- pressed -->
 <item android:state_checked="false"
       android:drawable="@drawable/locate_me" /> <!-- unchecked -->

But this does not work; reading the ToggleButton API (http://developer.android.com/reference/android/widget/ToggleButton.html), it appears that the only inherited xml attributes are

    XML Attributes
Attribute Name  Related Method  Description
android:disabledAlpha       The alpha to apply to the indicator when disabled. 
android:textOff         The text for the button when it is not checked. 
android:textOn      The text for the button when it is checked. 

There does not seem to be the android:state_checked attribute, despite the class having the method isChecked() and setChecked().

So, is there a way to do what I want in XML, or am I stuck with my messy workaround?

keeri
  • 809
  • 2
  • 13
  • 19
I82Much
  • 26,901
  • 13
  • 88
  • 119

1 Answers1

159

Your code is fine. However, the toggle button will display the first item in your selector that it matches, so the default should come last. Arrange the items in the following manner to ensure they will all be utilized:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true" android:state_pressed="true" /> //currently pressed turning the toggle on
    <item android:state_pressed="true" /> //currently pressed turning the toggle off
    <item android:state_checked="true" /> //not pressed default checked state
    <item /> //default non-pressed non-checked
</selector>
m_vitaly
  • 11,856
  • 5
  • 47
  • 63
  • 3
    That makes perfect sense; I never made the connection between selector and switch statements. – I82Much Oct 07 '09 at 19:31
  • You made my day... I had issues with button,checkbox and then tried radio button as well, finally this post was helpful. Thank you very much Vitaly Polonetsky and I82Much – David Prun Aug 18 '10 at 20:32
  • 8
    the documentation somewhere says that it reads from the top, stopping at the first state whose conditions are all met, so if default is at the top, it'll never get past that drawable. – Travis Apr 05 '12 at 20:20
  • 1
    @I82Much a `switch` would always select the "right one" regardless of order, this behaves more like a lengthy `if-elseif-elseif-else` with conditions like `state_x == true && state_y == false && state_z = true`. – TWiStErRob Dec 18 '14 at 10:46