18

Now I have a horizontal progress bar which is updated programmatically via ProgressBar setProgress method:

<ProgressBar
            style="@android:style/Widget.ProgressBar.Horizontal"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:layout_height="20dip"
            android:id="@+id/progressbar"
            >
    </ProgressBar>

Is there a way to convert this progress bar to a circle (pie chart) and to be able also to update the progress programmatically?

Example of what I want:

Mohsen Safari
  • 6,669
  • 5
  • 42
  • 58
Paul
  • 3,812
  • 10
  • 50
  • 73
  • do you mean you want an activity circle?? like the round one shown here: http://developer.android.com/design/building-blocks/progress.html If not, can you show a picture of what you mean? – Julian Higginson Sep 17 '12 at 11:45
  • and to be able also to update the progress programatically? -what u mean by this – Renjith K N Sep 17 '12 at 11:46
  • @Renjith K N : Update proogress programatically: for example at each 2 seconds I want to fill the circle with some color; is very similar with what is in this image: http://3.bp.blogspot.com/_sfxUTOTXTng/TQxMiOjIkNI/AAAAAAAAACo/xSeP2-nSXF4/s1600/progressBarStyleHorizontal.png , but I want to be in a circle. – Paul Sep 17 '12 at 11:50
  • @Julian Higginson: I want to update the progress bar indicator from time to time - let's say at each 2 seconds. – Paul Sep 17 '12 at 11:51
  • 3
    aaah.. so you want (for lack of a better description) a pie chart that goes towards 100%. Pretty sure this doesn't exist in standard android views. you might need to roll it yourself? or maybe go looking for android extension libraries.. maybe someone already did one? – Julian Higginson Sep 17 '12 at 15:14
  • is there a special place where I can find android extension libraries or I simply need to google it (which I've already did, but without any success...) ? – Paul Sep 19 '12 at 18:22

5 Answers5

22

You can either make a custom view (e.g. PieProgressView) or a custom Drawable (e.g. PieProgressDrawable). I took the custom view approach but either is perfectly viable.

A quick look at the source for Android's ProgressView yields a wildly complex implementation. Obviously, they are covering all their bases, but you don't have to write something that complex. We really only need two things:

  1. A member to keep track of the current progress.
  2. A method to draw the pie based on the current progress.

Number one is easy, just keep a member field that tracks the current percentage of the pie to draw. Number 2 is a bit more complicated but, luckily, we can do it with the standard Canvas draw methods.

Conveniently, Android's Canvas class provides a drawArc() method. You can use this to get your Pie effect. Assuming we stored our percentage in a member field called mPercent as a float between 0 and 1, an onDraw() method might look like this:

@Override
protected void onDraw(Canvas canvas) {

    final float startAngle = 0f;
    final float drawTo = startAngle + (mPercent * 360);

    // Rotate the canvas around the center of the pie by 90 degrees
    // counter clockwise so the pie stars at 12 o'clock.
    canvas.rotate(-90f, mArea.centerX(), mArea.centerY());
    canvas.drawArc(mArea, startAngle, drawTo, true, mPaint);

    // Draw inner oval and text on top of the pie (or add any other
    // decorations such as a stroke) here..
    // Don't forget to rotate the canvas back if you plan to add text!
    ...
}

Here's what the completed view looks like in a sample app:

PieProgressView in action!

Edit

Since posting, I've decided there's really no reason you need to implement a custom view. You can simply use a drawable and it's level property to do exactly what is needed. I made a gist with the full drawable.

dcow
  • 7,765
  • 3
  • 45
  • 65
  • Thank you, but it'd better write a example. – Omid Nazifi Feb 23 '15 at 06:45
  • @omidnazifi check the link. – dcow Feb 23 '15 at 18:22
  • I've check it, but it doesn't draw right image like above image! It just draw a circle. mDrawTo variable never fill by onLevelChange method. – Omid Nazifi Feb 24 '15 at 05:45
  • @omidnazifi [yes it is](https://gist.github.com/dcow/9493477#file-pieprogressdrawable-java-L73). – dcow Feb 24 '15 at 23:41
  • I used this drawable as a background on an Button, which rotated the text of the button. I fixed it with the following gist: https://gist.github.com/Liron-K/c705329ed213602db99f Summary: Don't rotate the canvas and adjust the start angle according. – Liron Apr 29 '15 at 14:25
  • 1
    @Liron cool I didn't know you could do negative start angles. This is much nicer. However, you do know you can just rotate the canvas back after you're done or save and pop the canvas, right? – dcow Apr 29 '15 at 18:00
  • I was actually more surprised that the canvas affected the button text at all. I was expecting it to just be the background. – Liron Apr 29 '15 at 18:02
  • The text is painted onto the same canvas as the background is drawn on. – dcow Apr 29 '15 at 18:09
3

Save yourself some time and before re-inventing the wheel (or the progress indicator), check if the one at http://github.com/Sage42/AndroidViewUtils works for you. Just add it to your project and have fun. It is customizable and offers options for Counting Up or Counting Down as well.

I forgot to add that the visuals looks almost exactly like the sample image from your question.

asiby
  • 3,229
  • 29
  • 32
2

Try this piece of code to create circular progress bar(pie chart). pass it integer value to draw how many percent of filling area. :)

private void circularImageBar(ImageView iv2, int i) {

    Bitmap b = Bitmap.createBitmap(300, 300,Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(b); 
    Paint paint = new Paint();

        paint.setColor(Color.parseColor("#c4c4c4"));
        paint.setStrokeWidth(10);
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawCircle(150, 150, 140, paint);
        paint.setColor(Color.parseColor("#FFDB4C"));
        paint.setStrokeWidth(10);   
        paint.setStyle(Paint.Style.FILL);
        final RectF oval = new RectF();
        paint.setStyle(Paint.Style.STROKE);
        oval.set(10,10,290,290);
        canvas.drawArc(oval, 270, ((i*360)/100), false, paint);
        paint.setStrokeWidth(0);    
        paint.setTextAlign(Align.CENTER);
        paint.setColor(Color.parseColor("#8E8E93")); 
        paint.setTextSize(140);
        canvas.drawText(""+i, 150, 150+(paint.getTextSize()/3), paint); 
        iv2.setImageBitmap(b);
}
Mani
  • 3,394
  • 3
  • 30
  • 36
0

For a circular progress bar, use:

style="?android:attr/progressBarStyle"

More details can be found here: What's the meaning of android:progressBarStyle attribute in ProgressBar?

As for setting its progress: the circular progress bar will keep spinning. Simply hide it after it's no longer needed.

Or you could implement something custom: show a TextView next to it and update it instead of using Progressbar.setProgress.

Step 0: setText("0%");
Step 1 (2 seconds later): setText("3%");
Step 2 (4 seconds later): setText("9%"); etc.
Community
  • 1
  • 1
Buffalo
  • 3,861
  • 8
  • 44
  • 69
  • Well, the main idea is that I do not want the progress bar to keep spinning...at each 2 seconds I want to fill the circle with some color; is very similar with what is in this image: 3.bp.blogspot.com/_sfxUTOTXTng/TQxMiOjIkNI/AAAAAAAAACo/… , but I want to be in a circle – Paul Sep 17 '12 at 11:53
  • The URL you added isn't valid. Customizing a ProgressBar doesn't seem very straightforward and should probably be asked in another question. Just search for "android custom progressbar". – Buffalo Sep 17 '12 at 12:06
  • this is the correct link, sorry: http://3.bp.blogspot.com/_sfxUTOTXTng/TQxMiOjIkNI/AAAAAAAAACo/xSeP2-nSXF4/s1600/progressBarStyleHorizontal.png – Paul Sep 17 '12 at 12:07
0

Even though it's an old question, I hope this answer can help future viewers.

Check out this library - https://github.com/lzyzsd/CircleProgress

For a simple circular progress, dynamic or static, this lib is pretty straightforward and has many attributes for easy customizability (like stroke width, start angle, inside background, text color, etc). For the UI which the OP wanted to achieve, this library would be perfect.

Circular progress sample image

vepzfe
  • 4,217
  • 5
  • 26
  • 46