Creating custom, fancy buttons in Android

Ever wondered how to properly create a custom button, which looks different when selected (or clicked) and can be resized? Fortunately it's quite easy in Android. Let's start by creating a bitmap for our button. I'm using Gimp for such things. That's what I got:



(I told you it would be fancy!)
As you can see, I created 4 variants. Accordingly: regular button, pressed button, selected (focused) button and the disabled button. I can create a 4-state button now with such XML:

 1 2 3 4 5 6 7 8 9101112
<?xml version="1.0" encoding="UTF-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false"
android:drawable="@drawable/button_menu_disabled" />
<item android:state_enabled="true"
android:state_pressed="true" android:drawable="@drawable/button_menu_pressed" />
<item android:state_enabled="true"
android:state_focused="true" android:drawable="@drawable/button_menu_selected" />
<item android:state_enabled="true"
android:drawable="@drawable/button_menu_normal" />
</selector>


Put all the files (button_menu_normal.png, button_menu_pressed.png, button_menu_selected.png, button_menu_disabled.png and the newly created button_menu.xml) in your res/drawable directory. That creates a drawable consisting of our three images, each for one state of the button. If I want to use it in a button, I have to specify my drawable as a button background (in some layout XML file):

 1 2 3 4 5 6 7 8 910
<Button android:id="@+id/new_game"
android:text="New game"
android:gravity="center"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15px"
android:layout_marginRight="15px"
android:layout_marginTop="10px"
android:background="@drawable/button_menu"
/>


Let's run the project! Oh, it doesn't look very nice...



That's because our buttons aren't resizing properly. Android just takes our bitmap and stretches it to fit the button. It's ugly.

Nine-patches, we need you!

Wait, nine-what? Nine-patches (or nine-patch drawables) are the Android's remedy to resizing problem. Basically a nine-patch is an almost-ordinary image, just it's treated by the system differently when resizing. Look at this:



That's a nine-patch image. Two things differ it from a regular image:
  • it has a 1-pixel border with some black pixels
  • it has to be saved with name like my_image.9.png
So what are those black pixels for? They indicate which parts of the image will be stretched. Look:



Android looks at those black pixels and divides the image in 9 parts using them and then resizes the image like that:
  • Parts 1, 3, 7 and 9 aren't resized at all
  • Parts 2 and 8 are resized horizontally
  • Parts 4 and 6 are resized vertically
  • Part 5 is resized horizontally and vertically


So only the pink parts are resized (in one axis) and the most pink part is resized on two axes. (that phrase sounds really weird)

That's how it looks when resized (I left your favourite pink color to show the patches):



Neat! You can create 9-patch images with any image manipulation program, but there's a little tool in the Android SDK for that purpose. Look for it in ANDROID_SDK_DIR/tools/draw9patch.



It's very simple, but it does the job. Play with it for a while or read some instructions here.

Ok, I've changed my button images to nine-patches (so button_menu_normal.png became button_menu_normal.9.png etc.). Let's change the code. The best thing is that we don't have to change anything! If Android sees the button_menu_normal.9.png file, it loads it automatically as a nine-patch image that's available under id @drawable/button_menu_normal. How cool is that?

Running the app gives us nicely resized buttons now.



Summary:
  • create your button image
  • create some variants for clicked, selected and disabled states
  • make 9-patches of it
  • create my_fancy_button.xml file in res/drawable directory
  • set it as your button background in the layout xml file

Easy! I'll continue to dig this subject and add some styling in the next post.

8 Response to "Creating custom, fancy buttons in Android"

  1. lilpiggie says:

    Thank you! This is extremely helpful! :)

    Thotep says:

    Glad I could help :)

    wow, amazing, thank you.

    Anonimowy says:

    Spasibo! :)

    Anonimowy says:

    Hvala!
    Simple and to the point, I just LOVE such tutorials.

    Zubair says:

    I needed to use Scalable custom buttons for my new project.
    its exactly what i was looking for.

    thanx

    this is awesome.....am trying it on textview but its showing me an error that such drawable resource file is not found...i have added the xml file in res->drawable...
    thanks..

    Anonimowy says:

    Very helpful! you could write an android tutorial with some of these tricks and i'm sure it would be awesome

Prześlij komentarz

Powered by Blogger