If you read many of my TechRepublic App Builder blog posts, you know I write a lot of tutorials on customizing various UI elements. My reasoning is twofold.

First, when it comes to wrinkling UI widgets, the Google documentation is sparse. This makes sense; the framework team at Google has a vested interest in encouraging developers to use their components on an “as-is” basis. This ensures a consistent look and feel across the platform. I agree with this decision on the part Google entirely, but there are times when I want to put my own spin on a widget. This plays into my second motivation for writing numerous tutorials on customizing Android UI elements.

In my opinion, one of the key differentiators of Android over other mobile phone operating systems is that with a bit of knocking, there is almost no door a developer can’t open on the platform. I’ve done extensive work with previous incarnations of Microsoft’s mobile offerings, and a few years ago I did some banging on RIM’s OS as well. In both of my first-hand experiences and from the second-hand experiences I’ve heard recounted by iOS engineers, no mobile platform on the market today comes close to allowing the amount of customization Android offers.

This TechRepublic tutorial on customizing a UI widget focuses on the SeekBar. If you are new to Android or haven’t stumbled across the SeekBar before, on any other platform it’s called a slider. Why the Googlites chose not to call it a slider I have no idea, but if you’ve used a computer since Windows 3.1, you will be familiar with the functionality.

The step-by-step tutorial that follows will have you up and running in no time. You can follow along or download the source here and import it directly into Eclipse.

1. Start a new Android project in Eclipse. Target Android 1.6 or greater. Be sure to rename the start-up activity to Main.java.

2. Before we can throw up our layout, we need to create a new folder in the /res directory called XML. Here we will define two simple drawables to use with our SeekBar.

progress_drawable.xml

<?xml version="1.0" encoding="UTF-8"?>

<shape xmlns:android=http://schemas.android.com/apk/res/android

android:shape="line">

<stroke android:width="2dp" android:color="#ff585858"/>

</shape>
thumb_drawable.xml

<?xml version="1.0" encoding="UTF-8"?>

<shape xmlns:android=http://schemas.android.com/apk/res/android

android:shape="rectangle">

<gradient android:startColor="#ffffffff" android:endColor="#ff585858" android:angle="270"/>

<size android:height="20dp" android:width="20dp"/>

</shape>

3. In the /res/layout folder, let’s define our main.xml layout. I am using a linear layout with some plain old vanilla text views. The SeekBar is pretty standard as well, with the exception of the last two attributes which are the only ingredients in our “secret sauce.” By pointing the progress drawable as well as the thumb to our XML files, we effectively override the default rendering of widget.

main.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical"

android:padding="40dip" >

<TextView

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="Customized Seek Bar Demo" android:textColor="#0000ff"

android:textStyle="bold"

android:textSize="16sp"

android:gravity="center" />

<SeekBar

android:paddingTop="20dip"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:gravity="center"

android:layout_gravity="center"

android:max="19"

android:progress="0"

android:secondaryProgress="0"

android:id="@+id/slider"

android:progressDrawable="@xml/progress_drawable"

android:thumb="@xml/thumb_drawable"/>

<TextView

android:paddingTop="10dip"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:gravity="center"

android:textColor="#ffffff"

android:text="50%"

android:textSize="16sp"

android:id="@+id/percent"/>

</LinearLayout>

4. We implement our Main.java file. In the /src folder, modify the wizard generated Main.java file to implement OnSeekBarChangedListener, and override the mandated callbacks.

package com.authorwjf.myseekbar;
import android.app.Activity;
import android.os.Bundle;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
public class Main extends Activity implements OnSeekBarChangeListener {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

setContentView(R.layout.main);

SeekBar sb = (SeekBar)findViewById(R.id.slider);

sb.setMax(100);

sb.setProgress(50);

sb.setOnSeekBarChangeListener(this); }
@Override
public void onProgressChanged(SeekBar v, int progress, boolean isUser) {

TextView tv = (TextView)findViewById(R.id.percent);

tv.setText(Integer.toString(progress)+"%");

}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}

That should do it. Running the app will display our custom SeekBar, and, respond in kind to sliding the widget from left to right or vice-versa. If you’re interested in seeing the subtle contrast between our custom SeekBar (Figure A) and the default one (Figure B), I’ve included images of both. Better yet, remove the progress drawable and thumb attributes from the main.xml layout, load the app to your device, and see for yourself.
Figure A

Custom SeekBar running on Gingerbread.

Figure B

Default SeekBar also on Gingerbread.