Sunday, July 22, 2012

Android: Drawing both side clipped Progress Bar

In most of the android application we can see some kind of progress bar with rounded corners as show below. Mostly in media players this used to indicate the curent duration and/or percentage of buffed content etc. These a mostly one side clipped. Let check how we can draw a both side clipped progress bar.


Android API provide a build in progress bar, application developer can make use of this in their development. For that they manly use ClipDrawable. In android, In case of these kind of stretchable background we can use nine-patch drawable those will be stretched in runtime and reduce both memory usage of application.

Assume you have created a nine-patch and added into res folder.

// Lets load the drawable and get it minimum height,
// here I am going to stretch horizontally so i get height.
Drawable drawable = getResources().getDrawable(R.drawable.progress);
int height = drawable.getMinimumHeight();
// If you check, you can identify that the drawable will be NinePatchDrawable.

// First lets examine how this nine patch getting drawn.
// set the boundary and pass the canvas to be drawn. 
drawable.setBounds(0, 0, getWidth(), height);
drawable.draw(canvas);
//this will draw the 0-100% progress bar.


//Now let us try a clipped progress bar.


//Create a clip drawable with above nine-patch, Gravity.LEFT , ClipDrawable.HORIZONTAL  
ClipDrawable clipDrawable1 = new ClipDrawable(drawable, Gravity.LEFT, ClipDrawable.HORIZONTAL);

//Set the level 9000, this will draw the 90% of the left part.
clipDrawable1.setLevel(9000);
clipDrawable1.setBounds(0, height, getWidth(), 2*height);
clipDrawable1.draw(canvas);
//this will draw 0-90%


//Lets create another ClipDrawable which will draw 80% of right part.
ClipDrawable clipDrawable2 = new ClipDrawable(clipDrawable1, Gravity.RIGHT, ClipDrawable.HORIZONTAL);
clipDrawable2.setLevel(8000);
clipDrawable2.setBounds(0, 2*height, getWidth(), 3*height);
clipDrawable2.draw(canvas);
//This draws 20%-80%
//But we expected this should draw 20%-90% progress bar.
//But issue is above clipDrawable2.setLevel(8000) set level of both Drawable.


//So set level of clipDrawable1 again and draw.
clipDrawable1.setLevel(9000);
clipDrawable2.setBounds(0, 3*height, getWidth(), 4*height);
clipDrawable2.draw(canvas);
//This will draw 20%-90% drawable.

Take, we can draw both sided progress bar using clip drawable one inside another, but set Level method will set all children's level, so after setting parent level we have to set chid levels in that order.