Adding State Graphics to an ImageButton with Inkscape

A good User Interface should be intuitive and attractive. Sometimes simple pictures can replace words, or many words on a screen. Symbols, colors and pictures can make a screen attractive and easy to use. If the screen design is using buttons with symbols instead of text then the ImageButton can be used. Provide the button with custom designed graphics using programs such as Inkscape. Out of the box it supports three visual states, normal, focused and pressed. Without a custom image the states are just plan colored rectangles, grey for normal, orange for focus, dark yellow for pressing. However it is easy to add a custom image for each of these states using a graphics program. This allows an ImageButton to be made unique. Inkscape (http://inkscape.org) is a good program for producing graphics for the Android platform. Inkscape is:

  • Fully featured
  • Free
  • Supports multiple screen densities (vector based)
  • Access to thousands of free images via the Open Clip Art Library (http://www.openclipart.org/)
  • Plenty of online tutorials.

Images can also be generated with programs such as GIMP, (http://www.gimp.org) or Paint.NET (http://www.getpaint.net/), but working with vector instead of raster images makes it easier to produce the variety of sizes needed for multiple screen densities. Those that are not familiar with working in Inkscape can use the built in tutorials (under the Help menu) and tutorials at http://inkscapetutorials.wordpress.com/ to teach themselves.

In the following example an ImageButton is used to represent Play (or Start, or Go). Open a new Android project in Eclipse using the File menu, select New then Android Project. Fill in the Project Name, here Button Press is used. Click Next and select the build target from the installed APIs, any will do, for example Android 1.5 if it is installed. Click Next and enter the Package Name in the required format, for example biz.tekeye.buttonpress, leave Create Activity as default, click Finish. The three images to be used can be built in Inkscape, or alternatively they are available from the Open Clip Art Library (http://www.openclipart.org/) as a Scalable Vector Graphic (SVG) file:

Image ImageButton State Project Name Open Clip Art Name Open Clip Art Search
Play Button in Normal State normal normal.png Architetto — pulsante 02 pulsante
 Play Button with Focus focus focus.png Blue Play Button With Focus play button
 Play Button Pressed pressed pressed.png Play Button Green With Blue Border play button

If an image is created in Inkscape or an SVG file opened in Inkscape then bitmaps for an ImageButton can be exported. Alternatively bitmaps can be generated directly from the Open Clip Art Library if a suitable image is found that requires no changes. For the former use the Inkscape Export Bitmap dialog to generate the required size bitmaps (using the Width or Height boxes) in the Portable Network Graphics (PNG) format. These can be exported directly to the relevant drawable folder.

Exporting Play Button from Inkscape

Ideally bitmaps will be generated for the various screen densities possible on Android devices. Medium density (160dpi) is the default density. Images placed in the drawable folder will be scaled for different density screens unless an equally named file is in the correct folder under the res folder: drawable-ldpi, drawable-mdpi (same as drawable), drawable-hdpi and drawable-xhdpi. The relative sizes are shown in the following diagram.

Android Screen RatiosThus a bitmap that is 60×60 on a medium density screen would be scaled to 45×45 on a ldpi screen, 90×90 on a hdpi screen and 120×120 on a xhdpi screen. Bitmaps produced from Inkscape for the various densities will reduce the pixellation that can occur from scaling the default bitmap. In many cases no additional code will be required to support the different density screens.

To generate a bitmap directly from an image’s Open Clip Art Library page type the image size required into the box below the View Image button and click the PNG button. The PNG will be generated with its largest x or y dimension matching the typed in value in pixels (an image that is taller than it is wide will have y to the given dimension, an image wider than it is tall will have x to the given dimension).  Save the generated file from the browser to the relevant directory and filename (use the context menu on the generated image and select Save Image As… or Save Picture As… depending upon the browser in use).

Convert Open Clip Art Library SVG image to Bitmap

Referencing an image from a View is usually achieved by setting an attribute to the name of the file in a drawable folder. However, an ImageButton needs three images, with the correct image required being based upon the button’s state. This is achieved via an XML selector file in the drawable directory, the relevant attribute (android:src in this case) then points to this XML file. In Eclipse select the File menu then Android XML File, set Resource Type  to Drawable and File to state_images.xml, selector for the Root Element, click Finish. The following code can be used to reference the images generated. Replace the code in state_images.xml with this (see our article Copying Code from the Articles for tips):

[code lang=”xml”]<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/pressed" />
<item android:state_focused="true"
android:drawable="@drawable/focus" />
<item android:drawable="@drawable/normal" />
</selector>[/code]

It is important that the image for the normal state appears last in the selector file. Android tests the state of the button and if no image for the given state is in the list then the last image is used, which is for the normal state. The layout below places two ImageButtons in a TableLayout, along with two TextViews for labels. Focus can be moved between the buttons using the trackball or joystick (or arrow keys). Replace the code in the res/layout/main.xml folder with this:

[code lang=”xml”]<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TableLayout android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TableRow android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<ImageButton android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/state_images"
android:background="@android:color/transparent"
android:padding="5dp"/>
<TextView android:id="@+id/textview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Press Me!"
android:textSize="20dp"
android:layout_gravity="center"/>
</TableRow>
<TableRow android:id="@+id/tableRow2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageButton android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/state_images"
android:background="@android:color/transparent"
android:padding="5dp"/>
<TextView android:id="@+id/textview2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No! Me!"
android:textSize="20dp"
android:layout_gravity="center"/>
</TableRow>
</TableLayout>
</LinearLayout>[/code]

Play using ImageButton in actionThe ImageButtons background attribute has been set to transparent, i.e. android:background=”@android:color/transparent”. This is to remove the ImageButton’s default state rectangles. Run the Button Press App in an emulator or on a device. No code is required to see the ImageButtons in action. To see the focus image use the keypad/trackball/joystick on the device or emulator to move the focus from button to button. The following code can be placed in the project to show the buttons working, here simply counting the button presses). Replace ButtonPressActivity class in the Java file under the src tree with this code. Imports for View, TextView and OnClickListener will require adding.

[code lang=”Java”]public class ButtonPressActivity extends Activity {
TextView tv1;    //for storing TextView references
TextView tv2;
long howManyClicks1=0L;    //count button clicks
long howManyClicks2=0L;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//get reference to the TextViews for later use
tv1 = (TextView) findViewById(R.id.textview1);
tv2 = (TextView) findViewById(R.id.textview2);
//attach an instance of HandleClick to the ImageButtons
HandleClick hc=new HandleClick();
findViewById(R.id.button1).setOnClickListener(hc);
findViewById(R.id.button2).setOnClickListener(hc);
}
private class HandleClick implements OnClickListener{
public void onClick(View arg0) {
if(arg0.getId()==R.id.button1)
tv1.setText("Pressed: " + ++howManyClicks1);
else
tv2.setText("Pressed: " + ++howManyClicks2);
}
}
}[/code]

ImageButton State PressedThis example used circular buttons, many other shapes and styles can be achieved with Inkscape. Download some code that covers this article ready for importing into an Android project. The code can also be accessed via the Android Example Projects page. See the article Move Android Code Between PCs Running Eclipse on how to import example code into an Eclipse project. A version of this article was produced for the Android Cookbook.

2 thoughts on “Adding State Graphics to an ImageButton with Inkscape

  1. Pingback: Button and Image Borders in Android with Nine Patch Files | Tek Eye

  2. I’ve started work on an Inkscape extension that lets you automatically export at multiple resolutions without having to do them all manually. It also supports exporting 9-patch PNGs. You can find it on CodePlex. Give it a go!

Leave a Reply

Your email address will not be published. Required fields are marked *

Human Verification: In order to verify that you are a human and not a spam bot, please enter the answer into the following box below based on the instructions contained in the graphic.