76

is it possible to create a toggle button in Android that has an image but no text? Ideally it would look like this:

Toggle Button With Image

Ive seen similar posts where the answer was to change the background but i want to preserve the Holo Light layout and just swap the text with an image.

I need to be able to programaticallly change the image source,

Any ideas how i would make this?

If this cant be done, is there a way i can make a normal button toggle on and off?

Community
  • 1
  • 1
Eduardo
  • 6,900
  • 17
  • 77
  • 121
  • There is AFAIK no easy way to replace text with an image besides swapping the entire 2 state background image with the one you want. You could try if you can set the text to be the image via [ImageSpan](http://developer.android.com/reference/android/text/style/ImageSpan.html) like in http://stackoverflow.com/questions/7616437/imagespan-in-a-widget – zapl Sep 03 '13 at 18:08

4 Answers4

123
  1. Can I replace the toggle text with an image

    No, we can not, although we can hide the text by overiding the default style of the toggle button, but still that won't give us a toggle button you want as we can't replace the text with an image.

  2. How can I make a normal toggle button

    Create a file ic_toggle in your res/drawable folder

    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item android:state_checked="false"
              android:drawable="@drawable/ic_slide_switch_off" />
    
        <item android:state_checked="true"
              android:drawable="@drawable/ic_slide_switch_on" />
    
    </selector>
    

    Here @drawable/ic_slide_switch_on & @drawable/ic_slide_switch_off are images you create.

    Then create another file in the same folder, name it ic_toggle_bg

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item android:id="@+android:id/background"  
              android:drawable="@android:color/transparent" />
    
        <item android:id="@+android:id/toggle"
              android:drawable="@drawable/ic_toggle" />
    
    </layer-list>
    

    Now add to your custom theme, (if you do not have one create a styles.xml file in your res/values/folder)

    <style name="Widget.Button.Toggle" parent="android:Widget">
       <item name="android:background">@drawable/ic_toggle_bg</item>
       <item name="android:disabledAlpha">?android:attr/disabledAlpha</item>
    </style>
    
    <style name="toggleButton"  parent="@android:Theme.Black">
       <item name="android:buttonStyleToggle">@style/Widget.Button.Toggle</item>
       <item name="android:textOn"></item>
       <item name="android:textOff"></item>
    </style>
    

    This creates a custom toggle button for you.

  3. How to use it

    Use the custom style and background in your view.

      <ToggleButton
            android:id="@+id/toggleButton"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="right"
            style="@style/toggleButton"
            android:background="@drawable/ic_toggle_bg"/>
    
Airon Tark
  • 8,900
  • 4
  • 23
  • 19
Rachit Mishra
  • 6,101
  • 4
  • 30
  • 51
  • 1
    This is brilliant thanks. Is there anywhere that i can find the @drawable/ic_slide_switch_on and off images used for the Holo Light Toggle Buttons? – Eduardo Sep 03 '13 at 18:39
  • 2
    they are in `sdk\platforms\android-17\data\res\drawable-hdpi` btn_toggle files, also you can see this android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html – Rachit Mishra Sep 03 '13 at 18:44
  • 1
    Thanks so much! if I could up vote you more than once I would :) – Eduardo Sep 03 '13 at 19:41
  • 3
    https://stackoverflow.com/a/11499595/4896468 this only set `background`, seems simpler – yurenchen Oct 16 '17 at 17:07
  • I had to replace `@+android:id/toggle` with [this](https://stackoverflow.com/a/31663119/8981474) to have it work properly. Otherwise it was the exact same solution I used. – isakbob Aug 10 '18 at 19:14
66

ToggleButton inherits from TextView so you can set drawables to be displayed at the 4 borders of the text. You can use that to display the icon you want on top of the text and hide the actual text

<ToggleButton
    android:id="@+id/toggleButton1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawableTop="@android:drawable/ic_menu_info_details"
    android:gravity="center"
    android:textOff=""
    android:textOn=""
    android:textSize="0dp" />

The result compared to regular ToggleButton looks like

enter image description here

The seconds option is to use an ImageSpan to actually replace the text with an image. Looks slightly better since the icon is at the correct position but can't be done with layout xml directly.

You create a plain ToggleButton

<ToggleButton
    android:id="@+id/toggleButton3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:checked="false" />

Then set the "text" programmatially

ToggleButton button = (ToggleButton) findViewById(R.id.toggleButton3);
ImageSpan imageSpan = new ImageSpan(this, android.R.drawable.ic_menu_info_details);
SpannableString content = new SpannableString("X");
content.setSpan(imageSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
button.setText(content);
button.setTextOn(content);
button.setTextOff(content);

The result here in the middle - icon is placed slightly lower since it takes the place of the text.

enter image description here

zapl
  • 63,179
  • 10
  • 123
  • 154
  • Nice idea, i never saw the drawable options on togglebutton – Eduardo Sep 03 '13 at 19:05
  • 1
    @clairharrison If you have a `TextView` and an `ImageView` you often get this: http://stackoverflow.com/questions/8318765/how-do-i-use-a-compound-drawable-instead-of-a-linearlayout-that-contains-an-imag - that's how I came up with that idea :) – zapl Sep 03 '13 at 19:15
  • ImageSpan worked great for me. I actually wanted a `ToggleButton` that looked like a normal `Button` (without the blue bar) with different on/off images, so I refresh the ImageSpan on button click with a new image based off `isChecked()`. – Josh Jan 28 '14 at 14:32
62

create toggle_selector.xml in res/drawable

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@drawable/toggle_on" android:state_checked="true"/>
  <item android:drawable="@drawable/toggle_off" android:state_checked="false"/>
</selector>

apply the selector to your toggle button

<ToggleButton
            android:id="@+id/chkState"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/toggle_selector"
            android:textOff=""
            android:textOn=""/>

Note: for removing the text i used following in above code

textOff=""
textOn=""
Melbourne Lopes
  • 4,817
  • 2
  • 34
  • 36
  • 1
    I Guess that's the easy thing to do. It Worked, thanks! – Daniel Jun 12 '14 at 16:12
  • 4
    Clean and simple! This answer should have more upvotes! – Swayam Apr 09 '15 at 12:02
  • Does anyone know how to adjust its vertical position without using negative number on margin/padding? – Ken Ratanachai S. Oct 02 '15 at 22:09
  • I used this answer, exactly as it is presented, and get [this](http://stackoverflow.com/questions/33290945/android-hide-stock-toggle-when-using-custom-background) error. The original toggle still displays on top of the background. – Birrel Oct 22 '15 at 21:21
  • Indeed the cleanest and easiest to understand and reuse. – Ajit Feb 15 '16 at 17:38
  • I was coming from an ImageView widget and couldn't get the image to show up. It took me sometime to realise the drawable attribute for a ToggleButton is "android:Background" and not "android:SRC" – Yahel Feb 02 '22 at 15:03
13

I know this is a little late, however for anyone interested, I've created a custom component that is basically a toggle image button, the drawable can have states as well as the background

https://gist.github.com/akshaydashrath/9662072

akshaydashrath
  • 1,025
  • 8
  • 18