Android Custom Progressbar with Rounded Corners using ClipDrawable

I’ll say right off the bat that this is a bit tricky to do, so you’ll probably want to start by downloading the sample project. Make sure you look closely at the namespaces and attributes. When you go to implement, if things aren’t working do a search in the code for “com.example” and change that to specific to your project.

For the project I’m on right now I was required to make some custom progress bars with rounded corners, something like this:

I found a few ways that got me close but not all the way there, as I posted on stackoverflow here.

Anyway, I had to roll my own based on RelativeLayout, and that seemed to work out pretty well. Here is what I came up with. At the core it uses ClipDrawable to mask the content of the progressDrawable. I didn’t see many examples out there of people using ClipDrawable for progress bars, though the usage is simple, so here is an example.

Here is the base class that extends RelativeLayout where the magic happens. Make sure and change the xmlns to the path to your resource folder. Should be something like com.packagename.whatever.

public class RoundProgress extends RelativeLayout {
    private ImageView progressDrawableImageView;
    private ImageView trackDrawableImageView;
    private int max = 100;
    public int getMax() {
        return max;
    }

    public void setMax(int max) {
        this.max = max;
    }

	public RoundProgress(Context context, AttributeSet attrs) {
		super(context, attrs);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(
                           Context.LAYOUT_INFLATER_SERVICE);
		inflater.inflate(R.layout.round_progress, this);
        setup(context, attrs);
	}

    protected void setup(Context context, AttributeSet attrs)
    {
        TypedArray a = context.obtainStyledAttributes(attrs,
            R.styleable.RoundProgress);

        final String xmlns=
                 "http://schemas.android.com/apk/res/path.to.resource.folder";
        int bgResource = attrs.getAttributeResourceValue(xmlns,
                "progressDrawable", 0);
        progressDrawableImageView = (ImageView) findViewById(
                R.id.progress_drawable_image_view);
        progressDrawableImageView.setBackgroundResource(bgResource);

        int trackResource = attrs.getAttributeResourceValue(xmlns, "track", 0);
        trackDrawableImageView = (ImageView) findViewById(R.id.track_image_view);
        trackDrawableImageView.setBackgroundResource(trackResource);

        int progress = attrs.getAttributeIntValue(xmlns, "progress", 0);
        setProgress(progress);
        int max = attrs.getAttributeIntValue(xmlns, "max", 100);
        setMax(max);

        a.recycle();

        ProgressBarOutline outline = new ProgressBarOutline(context);
        addView(outline);
    }

    public void setProgress(Integer value)
    {
        ClipDrawable drawable = (ClipDrawable)
                progressDrawableImageView.getBackground();
        double percent = (double) value/ (double)max;
        int level = (int)Math.floor(percent*10000);
        drawable.setLevel(level);
    }
}

In the layout file where you will embed your progress bar, you’ll need to add your xml namespace so that you can pass in custom attribues.  The opening node should look something like this:

<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:myNamespace="http://schemas.android.com/apk/res/path.to.resource.folder"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:orientation="vertical"/>

Then in that same layout xml file where you added your custom xmlns you’ll want to embed your actual progress bar like so:

<path.to.your.file.RoundProgress
        android:id="@+id/red_progress_bar"
        android:layout_width="200dip"
        android:layout_height="35dip"
        android:padding="3dip"
        myNamespace:max="100"
        myNamespace:progress="50"
        myNamespace:progressDrawable="@drawable/red_progress_clip"
        myNamespace:track="@drawable/progress_bar_fill_bg"
    />

Here is the red_progress_clip.xml that should be saved to res/drawable

<clip
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/red_progress_bar_fill"
    android:clipOrientation="horizontal"
    android:gravity="left"/>

Then you’ll need to save some attributes in the res/values/attrs.xml so that you can pass in custom vars via xml in the custom namespace

<resources>
    <declare-styleable name="RoundProgress">
      <attr name="progress" format="integer" />
      <attr name="max" format="integer" />
      <attr name="progressDrawable" format="integer" />
      <attr name="track" format="integer" />
    </declare-styleable>
</resources>

You’ll need this round_progress.xml for the progress bar’s view saved in the res/layout folder

<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <ImageView
        android:id="@+id/track_image_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
    />
     <ImageView
        android:id="@+id/progress_drawable_image_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
    />
</merge>

Here are two 9 patch images you’ll need. Feel free to tweak these images to get the look you want.

And thats it. Let me know in the comments if something doesn’t make sense, so I can clean up the post for others.

By: Bryce Barrand Categories: Blogroll / development Tags: , , , , , , , , , , , ,

11 Responses to Android Custom Progressbar with Rounded Corners using ClipDrawable

  1. Kinjan Shah says:

    Hi,
    Great work!
    though I tred using your example its not working for me. if you can help me with some source code for this it will be of great help.

    Kinjan

  2. wang_peng1 says:

    can you give your demo,when i copy your code,i also copy other things,it give me some trouble

  3. jitendra chaure says:

    I tried to do what you have explained on this site, but it is not working for me.Can you give me the complete code for an example.

  4. Jay says:

    What is ProgressBarOutline in the example above?

  5. Sergi says:

    I can’t get it working either.. a demo code would be great!

    Thanks.

  6. Ishwari Shah says:

    Hello Sir,
    Even i want to customize my progress bar,by changing the color and want to make it vertical bar in place of horizontal bar..I tried to follow steps mentioned on this site..but getting errors..So please can mail me on my email id the zip folder of source code of above..Please..Plz

  7. Bryce Barrand says:

    I hear you. I had something missing in the post. It is updated as well as a link to the source code. Good luck :)

  8. Stephen says:

    This and this seem like a more straightforward way to achieve the same result. Or am I missing something?

  9. @Stephen, those work if you don’t have picky designers who want it to look like the image at the beginning of the post :) If you can just reuse the seek bar, that is way to go.

  10. cyankahn says:

    Hey can you help me make custom progress bar as asked in this query. The solution there are not working :(

    http://stackoverflow.com/questions/8764035/vertical-progress-bar-in-android

  11. Pingback: Android: How can make progress bar like this | PHP Developer Resource

Leave a Reply