How-to: Customize Android progress bars

  • 0

How-to: Customize Android progress bars

Category : Uncategorized

Introduction to Android progress bars

This how-to will show you how to customize Android’s default progress bar to fully suit your needs. You will create an application that demonstrates different styles of progress bar. The end result will be something like this:

End result of learning how to style Android progress bars

If you want to take a look at the result on your own phone, you can just download the apk file. Or get the source.

After this how-to, you will know

  • How to fully customize Android’s horizontal progress bar
  • How to fully customize an indeterminate progress bar
  • What the default progress bar looks like on different API levels
  • How to use drawables to style widgets
The stock progress bar on different API levels

The stock progress bar on different API levels

The default progress bar

By default, the looks of the progress bar are determined by the system. This look has changed quite a bit through different Android versions.

The are good reasons to want your own, custom style for a progress bar. For instance, maybe your application features a color theme and you want the progress bar to fit in. Or maybe you want the progress bar to show a gradient. Whatever the reason, this tutorial will show you how to do it.

Customizing progress bars on Android

To start, download the project for this how-to. The starting project contains one Activity with no relevant code and one layout. The layout contains four progress bars, all in the default style. During this how-to we will change the style of three of the progress bars. When you’ve opened the project in your favorite IDE you should be able to view the layout and see something like this:

Tutorial starting point screenshot

Changing the progress bar drawable

Just like all the other widgets you use when creating an Android application, the progress bar allows changing some of its settings through the layout xml-file. For instance, by setting

1
android:progress="50"

the progress bar will show 50% progress. Note that this is the value that’s used in the tutorial project. You can experiment by changing this value anywhere between 0 and 100, you should see the progress indicator change accordingly in your visual editor.

By default, your progress bar will use the system drawable. For instance, on API level 17 this will be

1
@android:drawable/progress_horizontal_holo_light

This can be changed by adding a tag in the layout xml file. In order to change the drawable (and thus the style) for the second progress bar in this how-to, change the xml for that progress bar to:

01
02
03
04
05
06
07
08
09
10
<ProgressBar
    android:id="@+id/progressBar2"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_below="@+id/progressBar1"
    android:layout_marginTop="30dp"
    android:progress="50"
    android:progressDrawable="@drawable/progressbar2" />

You will probably get an error on this, which should be telling you your IDE is doing its job as we didn’t create the progressbar2 drawable yet. Let’s do that now to resolve this error. Add a new text file named progressbar2.xml to the /res/drawable directory. The contents of this xml file should be

1
2
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
</layer-list>

Note that there is no qualifier such as mdpi or xhdpi appended to the name of the drawable directory. This ensures that the drawable for the progressbar we’re about to create will be the same on all devices. Of course, if you don’t want that you could create different progress bar styles for different devices, but we won’t do so in this tutorial.

The element will be the root element of this drawable. It allows us to define an array of other drawables that will be drawn in the order they are defined. With this, the error your IDE throwed on the missing drawable should be gone. However, you’ll notice that the second scrollbar itself is gone as well. This too makes sense. After all, we’ve overruled the default drawable with an empty one, so nothing will be drawn!

A simple custom progress bar

To fix this we’ll have to define how the progress bar should be drawn. For this first one, we’ll make a progress bar with rounded corners. Its background will be a vertical gradient of two shades of gray (graydient!?), and when there’s progress it will show this by filling up with a gradient of blue to green from left to right. For this, put the following in the progressbar2.xml file:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
  <item android:id="@android:id/background">
    <shape>
      <corners android:radius="5dip" />
      <gradient
        android:angle="270"
        android:centerColor="#ff5a5d5a"
        android:centerY="0.5"
        android:endColor="#ff747674"
        android:startColor="#ff9d9e9d" />
    </shape>
  </item>
  <item android:id="@android:id/progress">
    <clip>
      <shape>
        <corners android:radius="5dip" />
          <gradient
            android:angle="0"
            android:endColor="#ff009900"
            android:startColor="#ff000099" />
      </shape>
    </clip>
  </item>
</layer-list>

This should result in a progress bar like this (shown here with 25%, 50%, and 75% progress):

A simple custom styled progress bar

Now, let’s go through the xml to learn how we got this effect. Notice that the xml contains two tags. The first one defines the background, the second defines how the progress bar will fill depending on the actual progress. The background is defined as a <shape>. This shape is said to have corners with a radius of 5dp, which causes the slightly rounded corners the progress bar has. Apart from this, the shape is defined by a <gradient> tag. The colors defined in the gradient are pretty self-descriptive. The angle is in degrees and defines the direction of the gradient. An angle of 270 degrees means that the start of the gradient will be at the bottom and the end will be at the top. Note that the angle has to be a multiple of 45, otherwise you’ll get this error: org.xmlpull.v1.XmlPullParserException: <internal -- stub if needed><gradient> tag requires 'angle' attribute to be a multiple of 45

The second tag also contains a shape with rounded corners and a gradient. This gradient is from left to right (the angle is 0), and it is from blue to green. Main difference with the background drawable is that this one is wrapped in a tag. The clip drawable  is not unique to progress bars, but in general can be used to reveal another drawable based on a level (in case of progress bars, the progress directly defines the clip drawable level). For a progress bar in this style to work the clip drawable is mandatory. Removing it will cause the progress bar to always show 100% progress.

An indeterminate progress bar

As a programmer, you can’t always tell how much progress is being made. Sometimes you just want an indicator to show that your program is actually working, but you don’t know if it’s 10%, 50%, or 99% done. This is called an indeterminate progress bar. Often, a spinning wheel animation is used for the indeterminate progress bar. However, there’s also a horizontal version of the indeterminate progress bar, which looks like this (but animated obviously):

Default indeterminate progress bar

To customize the indeterminate progress bar, add this tag to the layout xml file:

1
android:indeterminateDrawable="@drawable/progressbar3" android:minHeight="48dp"

Similar to how we changed the layout for the second progress bar by setting the drawable, we’ll change the layout for the indeterminate progress bar by setting the indeterminateDrawable value. Again, this will result in a warning in your IDE because there is no /res/drawable/progressbar3.xml. Let’s create that file, and fill it with:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="360" >
    <shape
        android:shape="oval"
        android:useLevel="false" >
        <size
            android:height="48dip"
            android:width="48dip" />
        <gradient
            android:centerColor="#ff000000"
            android:centerY="0.50"
            android:endColor="#ff00ff00"
            android:startColor="#ff000000"
            android:type="sweep"
            android:useLevel="false" />
    </shape>
</rotate>

Using this as drawable for the indeterminate progress bar will result in a progress bar that looks somewhat like the classic radar screens we all know from the movies:

Radar-styled indeterminate progress bar

This progress bar is rotating, because its top-level drawable is a tag, indicating it should rotate from 0 to 360 degrees around the center of the drawable. Apart from that, it’s defined mostly by the tag. This tag indicates that the shape should be oval, which results in a round shape because the available space is square. It’s filled with a sweep-gradient, which causes the typical green-to-black colors. And that without a single line of code, pretty cool, right?

Going crazy with progress bar styling

Now that we’ve got some tools that help us create custom progress bars, we’re mainly limited by our imagination. What kind of crazy progress bar could you come up with? I’ll give one example to end this tutorial:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:id="@android:id/background">
        <shape android:shape="rectangle" >
            <corners android:radius="15dip" />
            <stroke
                android:width="5dip"
                android:color="#ff0000ff" />
            <gradient
                android:centerColor="#ff000000"
                android:endColor="#ffff0000"
                android:gradientRadius="200"
                android:startColor="#ff00ff00"
                android:type="radial" />
        </shape>
    </item>
    <item android:id="@android:id/progress">
        <rotate
            android:fromDegrees="0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="90" >
            <shape android:shape="rectangle" >
                <corners android:radius="15dip" />
                <solid
                    android:color="#aaf4e329"
                    />
                <stroke
                    android:width="5dip"
                    android:color="#ff0000ff" />
            </shape>
        </rotate>
    </item>
</layer-list>

This will give you a progress bar on drugs, like this (showing 0%, 25%, 50%, 75%, and 100% progress):

Progress bar styled crazy

I’ll leave it to you to figure out how we got this effect. Good luck with your own progress bars!


Leave a Reply