Two Progress Bars for Android

I built two different views to show progress bars in Android. One is a horizontal progress bar and the other is a vertical progress bar, made up of a stack of horizontal bars. Here they are displayed in a demo app, running on a Galaxy Nexus phone.



For the horizontal progress, you can control the colors used, the width and height of the bar, and the number of divisions. For the vertical progress bar, I wanted it to look like a stack of bars. When you run the demo app, you can see the values change by touching a progress bar.

How It Works

The three main parts of this demo app are the following:

  1. The main layout file.
  2. The definition of the custom attributes that are used in the layout file.
  3. The view definition itself: ProgressBarView.

The layout xml file for the activity is activity_main.xml. Within it are three view definitions for the progress bars. The first is the vertical progress bar. Note that it uses a custom view type and note that the view has custom attributes. Examples are bar_initial_value, bar_num_divisions, and bar_orientation. A value of 1 for bar_orientation indicates a vertical progress bar.


The first horizontal bar definition looks like this:



Inside the activity_main.xml file, there is a line at the top that tells the system that there are custom definitions being used. It is the line with “xmlns:custom”.

<FrameLayout xmlns:android=""

The custom attributes are defined in the values folder in a file named “attrs_views.xml”. Each definition describes the name and format of a custom style that can appear in the layout xml file. The declare-styleable part indicates the name of the view that the attributes apply to.

 <declare-styleable name="ProgressBarView">
 <attr name="bar_color1" format="color"/>
 <attr name="bar_color2" format="color"/>
 <attr name="bar_initial_value" format="integer"/>
 <attr name="bar_num_divisions" format="integer"/>
 <attr name="bar_height" format="dimension"/>
 <attr name="bar_spacing" format="dimension"/>
 <attr name="bar_orientation" format="integer"/>

In class definition for ProgressBarView, the attribute values are processed in the constructor code. The code looks to see an attribute is present, and if it is, it overrides the default value that would be used.

public ProgressBarView (Context context, AttributeSet attrs, int style) {
   super (context, attrs, style);
   readAttrs (context, attrs);
 * Read the attribute set and set view variables.
 * @param attrs AttributeSet
 * @return void
private void readAttrs (Context context, AttributeSet attrs) {
  TypedArray a = context.obtainStyledAttributes (attrs, 
  final int N = a.getIndexCount();
  for (int i = 0; i < N; ++i) {
     int attr = a.getIndex(i);
     switch (attr) {
     case R.styleable.ProgressBarView_bar_color1:
       int c = a.getColor (attr, Color.WHITE);
       setBarColor1 (c);
     case R.styleable.ProgressBarView_bar_color2:
       int c2 = a.getColor (attr, Color.GRAY);
       setBarColor2 (c2);
     case R.styleable.ProgressBarView_bar_initial_value:
       int val = a.getInt (attr, 0);
       setValue (val);
     case R.styleable.ProgressBarView_bar_num_divisions:
       int numdiv = a.getInt (attr, DEFAULT_NUM_DIVISIONS);
       setNumDivisions (numdiv);
     case R.styleable.ProgressBarView_bar_height:
       int bh = a.getDimensionPixelSize (attr, DEFAULT_BAR_PIXEL_HEIGHT);
       setBarHeight (bh);
     case R.styleable.ProgressBarView_bar_spacing:
       int bspace = a.getDimensionPixelSize (attr, DEFAULT_BAR_PIXEL_SPACING);
       setBarSpacing (bspace);
     case R.styleable.ProgressBarView_bar_orientation:
       int orient = a.getInt (attr, DEFAULT_ORIENTATION);
       setBarOrientation (orient);
   }  // end for

As is typical for a subclass of View, the actual drawing of the view is done in the onDraw method . By the time it runs, all the custom attributes have been handled and their values are in instance variables of the view. My onDraw  method checks to see which orientation is in effect and then calls a method to draw the bars either horizontally or vertically.

@Override protected void onDraw(Canvas canvas) {
 int orient = getBarOrientation ();
if (orient == VERTICAL_ORIENTATION) drawOnCanvasV (canvas);
 else drawOnCanvasH (canvas);

Let’s look at the code for the horizontal progress bar. The progress bar it draws is made up of N rectangles., where N is defined by the number of divisions. For example, if the number of divisions is 10 and current value is 2, 2 bars will be drawn with bar color 1, followed by 8 bars of bar color 2.

It starts by examining the variables that control the display: number of divisions, bar height, spacing, etc. Then it draws N rectangles, one for each of the divisions.

 * Draw progress bar oriented horizontally.
void drawOnCanvasH (Canvas canvas) {
 int maxValue = getNumDivisions ();
 int numValue = getValue ();
 if (numValue > maxValue) numValue = maxValue;
 if (numValue < 0) numValue = 0;
 int bspace = getBarSpacing ();
 int customBarHeight = getBarHeight ();
 int numDivs = getNumDivisions ();
 if (numDivs <= 0) numDivs = 1;
 int currentVal = getValue ();
 int color1 = getBarColor1 ();
 int color2 = getBarColor2 ();
 int vw = getWidth ();
 int vh = getHeight ();
 float vwf = (float) vw;
 float vhf = (float) vh;
// Draw a row of bars. Use up the entire width of the view. 
 // Add spacing between the bars. Number of spaces is 1 less than the numDivs.
 float x = 0.0f + getPaddingLeft ();
 float y = 0.0f + getPaddingTop ();
 float barWidth = (vwf - (float) ((numDivs - 1) * bspace) 
                  - getPaddingLeft () - getPaddingRight ()) 
 / (float) numDivs;
 float deltaX = barWidth + bspace;
 float deltaY = 0.0f;
 float barHeight = vhf - getPaddingTop () - getPaddingBottom ();
 if (customBarHeight > 0) barHeight = customBarHeight;
 int rcolor = color1; 
 // Draw N rectangles. Choose the color based on whether the current value 
 // is larger than the index value for the rectangle.
 // The width of the bar is chosen to account for the space 
 // that gets added between rectangles.
 for (int j = 0; j < numDivs; j++) {
   if (j < numValue) rcolor = color1;
   else rcolor = color2;
   mPaint.setColor (rcolor);
   canvas.drawRect (x, y, x + barWidth, y + barHeight, mPaint);
   x += deltaX;
   y += deltaY;

When you use this view in a more dynamic application, you do what you normally do with a view. That is, you set values and call the view’s invalidate method to get the changes to appear. An example of that is shown in the onClick method in the MainActivity class.

public void onClick(View v) {
  ProgressBarView pb = (ProgressBarView) v;
  int numDivisions = pb.getNumDivisions ();
  int val = pb.getValue ();
  if (val > numDivisions) val = 0;
  pb.setValue (val);
  pb.invalidate ();

Source Code

You can download the source code for this demo from  the website. Click here: download zip file from The zip is attached at the bottom of that page. After you import the project into Eclipse, it’s a good idea to use the Project – Clean menu item to rebuild the project.

This demo app was compiled with Android 4.2 (API 17). It works in all API levels from API 10 on up.


Creating a View Class 

About Bill Lahti

Bill Lahti is a software engineer building mobile applications and knowledge management solutions. Two of his interests are writing for this blog and building Android apps, with strategy games being an area of particular interest.
This entry was posted in Android and tagged , , , , . Bookmark the permalink.

4 Responses to Two Progress Bars for Android

  1. Pingback: My Android Programming Tutorials By Topic | More Is Not Always Better

  2. Pingback: More Mobile Enemy in Starship App | More Is Not Always Better

  3. Chris Bessant says:

    Hi Bill

    Thanks for the progress bar sample, which I’m looking to use in my project.

    Do you have an example where you create a progress bar view programatically? I’m trying to do so but struggling.

    Thanks from London


    • Bill Lahti says:

      I don’t have an example, but I have a suggestion of something to try. When I have a view or layout that I don’t know how to do programmatically, I put in more than one layout/view and set their visibility to invisible. Then in the view code (onCreate, onResume, etc.), I check the various conditions related to use of the view and setVisibility so that just the right ones are visible. If conditions change later, a few calls to setVisibility takes care of the change. I prefer that rather adding and removing child views. Furthermore, the Android designers have put a lot of useful features into layouts (themes, styles, etc.), and trying to do those things in code is something I try to avoid.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s