33

When I add horizontal ProgressBar it behaves as expected -- I set the progress value and it shows it.

However when I add ProgressBar (circular) it spins. And that's it. In such form it is more "please wait" indicator, that any progress bar, because progress value is not shown.

So my question is (assuming Progress in name means progress) -- how to stop spinning and shows progress value? For example if I set max to 100, and value to 50 I would expect to see half-circle arc.

In other words how to make circular ProgressBar to behave like horizontal ProgressBar, with only exception of the shape?

greenoldman
  • 16,895
  • 26
  • 119
  • 185
  • the circular progressbar is referred to as "indeterminate" for a reason. you will probably need to create a custom drawable of some kind. – toadzky Oct 16 '12 at 17:42
  • I set `indeterminate` to false. But nevertheless, what the `progress` and `max` are for if no matter what I set, the image does not change at all? – greenoldman Oct 16 '12 at 17:43
  • `ProgressBar` should be an actual bar when using `indeterminate`. Like when you download a file on Google Drive. Can we see the code you're using? – Cat Oct 16 '12 at 18:10
  • 2
    @Eric, there is no code, I dragged&dropped circular ProgressBar, but no matter how I configure it it just spins. I.e. the `max` and `progress` values are completely ignored. – greenoldman Oct 16 '12 at 20:11

5 Answers5

17

I know that this is an old post but I ran into the same issue and I make it work.

It is actually easier than you think, you have to set a custom progress in an xml file inside your drawable folder and handle the attributes "fromDegrees" and "toDegrees" from the < rotate > tag:

This is the code for custom_progress.xml (you can customize yours as you like but you must not modify "fromDegrees" and "toDegrees")

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <shape
            android:innerRadiusRatio="2.3"
            android:shape="ring"
            android:useLevel="false"
            android:type="sweep"
            android:thicknessRatio="15.0">
            <solid android:color="#0099ff"/>
        </shape>
    </item>
    <item android:id="@android:id/progress">
        <rotate
            android:pivotX="50%"
            android:pivotY="50%"
            android:fromDegrees="-90"
            android:toDegrees="-90">
            <shape
                android:innerRadiusRatio="2.3"
                android:shape="ring"
                android:angle="0"
                android:type="sweep"
                android:thicknessRatio="15.0">
                <solid android:color="#e0e0e0"/>
            </shape>
        </rotate>
    </item>
</layer-list>

And for your progress bar you have to set this attributes:

<ProgressBar
    android:id="@+id/progressbar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:indeterminate="false"
    android:max="100"
    android:progress="20"
    android:progressDrawable="@drawable/custom_progress" />

What is happening here is that the progress will start in degree -90 which for me is the top side of the progress bar view and towards the right and it will continue towards the same degree, this will make the view progress to start and end in the same degree.

NOTE: If you set 0 for both "fromDegrees" and "toDegrees" the progress will start from the right side of the circle.

Hope it helps people with the same requirement.

Fabian Almaraz
  • 171
  • 1
  • 3
7

Since Api 21 you can do something like that: Assuming that your ProgressBar defind this way:

 <ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
    style="?android:attr/progressBarStyleLarge"
    android:id="@+id/progress_bar"
    android:layout_width="@dimen/item_width"
    android:layout_height="@dimen/item_height"
    android:clickable="false"
    android:indeterminate="true"
    android:indeterminateDrawable="@drawable/progress"/>

and this is progress.xml:

<shape
    android:innerRadiusRatio="3"
    android:shape="ring"
    android:thicknessRatio="8"
    android:useLevel="false" >

    <size
        android:height="76dip"
        android:width="76dip" />

    <gradient
        android:angle="0"
        android:endColor="@color/colorGrayText"
        android:startColor="@android:color/transparent"
        android:type="sweep"
        android:useLevel="false" />

</shape>

Now you can do this on your ProgressBar:

 ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar);
        if (progressBar != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                RotateDrawable rotateDrawable = (RotateDrawable) progressBar.getIndeterminateDrawable();
                rotateDrawable.setToDegrees(0);
            }
        }
yshahak
  • 4,996
  • 1
  • 31
  • 37
  • 1
    Thank you for this solution, it worked perfectly for me. How would you start spinning again if you wanted to? – markdrake Feb 27 '17 at 19:18
  • I realized how to do it, what this code is doing is spin from 0 to 0 degrees (and looks stopped), so to reset the animation spinning just rever to rotateDrawable.setToDegrees(360); and that should work. I added the comment for anybody looking for this answer. – markdrake Feb 27 '17 at 19:35
  • Great addition pal! I can add it to the question if it's ok. – yshahak Feb 28 '17 at 06:27
  • seems Like I'm doing something wrong cause I'm getting class exception when casting the drawable to RotateDrawble. I added the progressbar programatically progressBar = new ProgressBar(getContext()); progressBar.setMax(maxDurationInMilliSec / 1000); progressBar.setProgress(0); progressBar.setIndeterminate(true); progressBar.setIndeterminateDrawable(getContext().getDrawable(R.drawable.circle_loader)); – Roee May 08 '17 at 11:00
  • If you don't set `android:indeterminateDrawable` in `xml` as I wrote in the answer, you can't use in this code like this. – yshahak May 08 '17 at 11:32
2

Like toadzky commented, there's no baked-in method. You might try this ProgressWheel. If nothing else, it should give you idea of how to implement it.

Geobits
  • 22,218
  • 6
  • 59
  • 103
  • 2
    Thank you. Strange that such buggy piece of code was published (ProgressBar) in the first place. – greenoldman Oct 16 '12 at 20:12
  • 2
    No prob, but it's not really buggy. It does exactly what it's designed for. The circular one is for use when you don't know how long something will take. The Android UI consistently uses bar-type for indicating "percentage done", and circular for "work in progress", so users understand what each means. – Geobits Oct 16 '12 at 21:17
  • 2
    Ok, but "work in progress" does not require such properties. It is on or off. Adding dead properties is design flaw (or a bug). – greenoldman Oct 16 '12 at 21:20
0

For determinate progress bar means the progress bar which doesn't keep on rotating and user can set a fixed percentage over that.

<ProgressBar
                android:id="@+id/pb_sharpness"
                style="@style/Widget.AppCompat.ProgressBar.Horizontal"
                android:layout_width="@dimen/dp_50"
                android:layout_height="@dimen/dp_50"
                android:layout_marginTop="@dimen/dp_16"
                android:indeterminate="false"
                android:max="100"
                android:progressDrawable="@drawable/custom_progress_bar"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

For adding drawable to above progress bar

 <?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
    <shape
        android:innerRadiusRatio="2.3"
        android:shape="ring"
        android:useLevel="false"
        android:type="sweep"
        android:thicknessRatio="15.0">
        <solid android:color="@color/white_color"/>
    </shape>
</item>
<item android:id="@android:id/progress">
    <rotate
        android:pivotX="50%"
        android:pivotY="50%"
        android:fromDegrees="180"
        android:toDegrees="0"
        >
        <shape
            android:innerRadiusRatio="2.3"
            android:shape="ring"
            android:angle="0"
            android:type="sweep"
            android:thicknessRatio="15.0">
            <gradient
                android:startColor="@color/color_5646F3"
                android:endColor="@color/color_ED88FE" />
        </shape>
    </rotate>
</item>
Sahil Bansal
  • 609
  • 8
  • 6
0

You can access the visibility property of the progress bar and set it to invisible when you need it to be invisible like this

ProgressBar progressBar = view.findViewById<ProgressBar>(R.id.progressbar)

progressBar.visibility = ProgressBar.INVISIBLE
Dharman
  • 30,962
  • 25
  • 85
  • 135