views:

1640

answers:

1

How can I have an imagebutton stay in the 'pressed' state when it is clicked? Basically I just want the background to be the depressed background, but I can't figure out how to set it. At the moment, I've just copied the selected button background into my res folder, but when I set it as the background, it becomes blurry (since the original image is bigger than the button itself).

Normal Background: alt text What I'm getting: alt text alt text

Also I don't believe I can actually use this method considering the many different UI layouts. The button should stay pressed as per the UI the user is using.

+2  A: 

There are a few ways of doing this:

First, you can simply use an ImageButton, and manually toggle its image drawable on click in Java. This is what the stock Music player on Android does for the 'shuffle' button, for example. Although you won't have control over the button background in its checked state, you'll be able to swap out the image, which may be favorable from an Android UI-consistency perspective.

Another option is to use a complex set of drawables and nine-patches to get an image inside a ToggleButton, with the option of changing the background and/or the image resource upon toggle. That's the option I'll show below. But remember, be cautious about UI consistency before doing this.


res/layout/foo.xml

...
<ToggleButton
    android:textOn="" android:textOff=""
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/shuffle_button" />
...

res/drawable/shuffle_button.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"&gt;
    <!-- use "@android:drawable/btn_default" to keep consistent with system -->
    <item android:drawable="@drawable/toggle_button_background" />
    <item android:drawable="@drawable/shuffle_button_image" />
</layer-list> 

res/drawable/toggle_button_background.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
    <!-- checked state -->
    <item android:state_pressed="false" android:state_checked="true"
          android:drawable="@drawable/btn_default_checked" />

    <item android:state_window_focused="false" android:state_enabled="true"
          android:drawable="@drawable/btn_default_normal" />
    <item android:state_window_focused="false" android:state_enabled="false"
          android:drawable="@drawable/btn_default_normal_disable" />
    <item android:state_pressed="true"
          android:drawable="@drawable/btn_default_pressed" />
    <item android:state_focused="true" android:state_enabled="true"
          android:drawable="@drawable/btn_default_selected" />
    <item android:state_enabled="true"
          android:drawable="@drawable/btn_default_normal" />
    <item android:state_focused="true"
          android:drawable="@drawable/btn_default_normal_disable_focused" />
    <item android:drawable="@drawable/btn_default_normal_disable" />
</selector>

res/drawable/shuffle_button_image.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
    <item android:drawable="@drawable/ic_mp_shuffle_on_btn" android:state_checked="true" />
    <item android:drawable="@drawable/ic_mp_shuffle_off_btn" />
</selector>

Image files

  • btn_default_<state>.9.png can be found in frameworks/base.git under core/res/res/drawable-hdpi and core/res/res/drawable-mdpi (also ldpi). WARNING: if you use these, your app will look inconsistent on devices with customized OS UIs (i.e. HTC's Sense UI).
  • ic_mp_shuffle_<state>_btn.9.png need to be nine-patches, so that the image gets centered and not stretched to fit the button. Below are example hdpi versions of the icon:

res/drawable-(h|m|ldpi)/ic_mp_shuffle_(on|off)_btn.9.png

ic_mp_shuffle_on_btn.9.png ic_mp_shuffle_off_btn.9.png


Final Note: Remember to be consistent with the system UI when possible, and be mindful of the fact that your app may run on devices with customized versions of the OS that have different graphics for UI elements like buttons. An example of this is HTC Sense, which has green buttons in place of the grey/orange/yellow ones in stock Android. So, if you end up copying the btn_default_... PNG files from the open source repository to create a toggle-able button background, you'll break consistency on those devices.

Roman Nurik
I suppose there's no way to access the resources directly from the OS itself so that it would grab the correct background every time?
GuyNoir
No, because `@android:drawable/btn_default_normal` and the like (the nine-patches) are not public, but `@android:drawable/btn_default` (the selector) is public. Unfortunately the selector doesn't include a checked state.
Roman Nurik
Bah. Alright, thanks for the info.
GuyNoir