How to Create a circular progressbar in Android which rotates on it?

Saurav Srivastava picture Saurav Srivastava · Jan 24, 2014 · Viewed 257.4k times · Source

I am trying to create a rounded progressbar. This is what I want to achieve

There is a grey color background ring. On top of it, a blue color progressbar appears which moves in a circular path from 0 to 360 in 60 or whatever amount of seconds.

enter image description here

Here is my example code.

<ProgressBar
            android:id="@+id/ProgressBar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            style="?android:attr/progressBarStyleLarge"
            android:indeterminateDrawable="@drawable/progressBarBG"
            android:progress="50"
            />

To do this, in the drawable "progressBarBG", I am creating a layerlist and inside that layer list I am giving two items as shown.

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
    <shape
            android:shape="ring"
            android:innerRadius="64dp"
            android:thickness="8dp"
            android:useLevel="false">

        <solid android:color="@color/grey" />
    </shape>
</item>

<item android:id="@android:id/progress">
    <clip>
        <shape
                android:shape="ring"
                android:innerRadius="64dp"
                android:thickness="8dp"
                android:useLevel="false">

            <solid android:color="@color/blue" />
        </shape>
    </clip>
</item>

Now, the first grey ring is generated fine. The blue ring however starts from the left of the drawable and goes to the right just like how a linear progressbar works. This is how it shows at 50% progress with the red color arrow showing direction.

enter image description here

I want to move the blue progressbar in circular path as expected.

Answer

M. Reza Nasirloo picture M. Reza Nasirloo · Sep 10, 2014

Here are my two solutions.

Short answer:

Instead of creating a layer-list, I separated it into two files. One for ProgressBar and one for its background.

This is the ProgressDrawable file (@drawable folder): circular_progress_bar.xml

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="270"
    android:toDegrees="270">
    <shape
        android:innerRadiusRatio="2.5"
        android:shape="ring"
        android:thickness="1dp"
        android:useLevel="true"><!-- this line fixes the issue for lollipop api 21 -->

        <gradient
            android:angle="0"
            android:endColor="#007DD6"
            android:startColor="#007DD6"
            android:type="sweep"
            android:useLevel="false" />
    </shape>
</rotate>

And this is for its background(@drawable folder): circle_shape.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="ring"
    android:innerRadiusRatio="2.5"
    android:thickness="1dp"
    android:useLevel="false">

    <solid android:color="#CCC" />

</shape>

And at the end, inside the layout that you're working:

<ProgressBar
        android:id="@+id/progressBar"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:indeterminate="false"
        android:progressDrawable="@drawable/circular_progress_bar"
        android:background="@drawable/circle_shape"
        style="?android:attr/progressBarStyleHorizontal"
        android:max="100"
        android:progress="65" />

Here's the result:

result 1

Long Answer:

Use a custom view which inherits the android.view.View

result 2

Here is the full project on github