Android: Start the circular progress bar from top

2020-05-15 07:00发布

问题:

I have defined a circular progress bar using the following drawable "ciruclar_progress_bar.xml"

<?xml version="1.0" encoding="utf-8"?>
<item android:id="@android:id/progress">
    <shape
        android:innerRadiusRatio="2.5"
        android:shape="ring"
        android:thicknessRatio="25.0" >
        <gradient
            android:centerColor="@color/gray"
            android:endColor="@color/gray"
            android:startColor="@color/gray"
            android:type="sweep" />
    </shape>
</item>
<item android:id="@android:id/secondaryProgress">
    <shape
        android:innerRadiusRatio="2.5"
        android:shape="ring"
        android:thicknessRatio="25.0" >
        <gradient
            android:centerColor="@color/green"
            android:endColor="@color/green"
            android:startColor="@color/green"
            android:type="sweep" />
    </shape>
</item>

and I have used this drawable for ProgressBar in my layout using the following code

  <ProgressBar
            android:id="@+id/progressWheel"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="152dp"
            android:layout_height="152dp"
            android:layout_centerInParent="true"
            android:progress="100"
            android:indeterminate="false"
            android:progressDrawable="@drawable/circular_progress_bar" />

I used following code to show progress on the ProgressBar

progressWheel.setSecondaryProgress(percent);

(Used secondary progress because the green color should come on top of the black color of the ring.)

This draws the circular ProgressBar whose starting position is on the right (0°) as shown in the following image

I want the progress to start from the top as shown in the following image

I tried putting android:angle="270" in the gradient tag of drawable xml but had no luck. Is there any way I can start the sweep angle from the top?

回答1:

Try specifying rotation degrees to your progress items.

<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:id="@android:id/progress">
        <rotate
            android:fromDegrees="270"
            android:toDegrees="270"
            android:pivotX="50%"
            android:pivotY="50%" >
            <shape
                android:innerRadiusRatio="2.5"
                android:shape="ring"
                android:thicknessRatio="25.0" >
                <gradient
                    android:centerColor="@color/gray"
                    android:endColor="@color/gray"
                    android:startColor="@color/gray"
                    android:type="sweep" />
            </shape>
        </rotate>
    </item>
    <item android:id="@android:id/secondaryProgress">
        <rotate
            android:fromDegrees="270"
            android:toDegrees="270"
            android:pivotX="50%"
            android:pivotY="50%" >
            <shape
                android:innerRadiusRatio="2.5"
                android:shape="ring"
                android:thicknessRatio="25.0" >
                <gradient
                    android:centerColor="@color/green"
                    android:endColor="@color/green"
                    android:startColor="@color/green"
                    android:type="sweep" />
            </shape>
        </rotate>
    </item>
</layer-list>    


回答2:

You can also apply a rotation to your ProgressBar in layout XML. In your case -90° would solve your problem.

    <ProgressBar
        android:id="@+id/progressDemo"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="152dp"
        android:layout_height="152dp"
        android:layout_centerInParent="true"
        android:indeterminate="false"
        android:progress="10"
        android:rotation="-90"
        android:progressDrawable="@drawable/circular_progress_bar" />


回答3:

Here's how I made circular progressbar with percentage inside circle in pure code without any library.

Reference is taken from here : circular progress bar android

first create a drawable file called circular.xml

<?xml version="1.0" encoding="utf-8"?>

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/secondaryProgress">
        <shape
            android:innerRadiusRatio="6"
            android:shape="ring"
            android:thicknessRatio="20.0"
            android:useLevel="true">


            <gradient
                android:centerColor="#999999"
                android:endColor="#999999"
                android:startColor="#999999"
                android:type="sweep" />
        </shape>
    </item>

    <item android:id="@android:id/progress">
        <rotate
            android:fromDegrees="270"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="270">

            <shape
                android:innerRadiusRatio="6"
                android:shape="ring"
                android:thicknessRatio="20.0"
                android:useLevel="true">


                <rotate
                    android:fromDegrees="0"
                    android:pivotX="50%"
                    android:pivotY="50%"
                    android:toDegrees="360" />

                <gradient
                    android:centerColor="#00FF00"
                    android:endColor="#00FF00"
                    android:startColor="#00FF00"
                    android:type="sweep" />

            </shape>
        </rotate>
    </item>
</layer-list>

Now in your activity_main.xml add following:

  <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/dialog"
    tools:context="com.example.parsaniahardik.progressanimation.MainActivity">

    <ProgressBar

        android:id="@+id/circularProgressbar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:indeterminate="false"
        android:max="100"
        android:progress="50"
        android:layout_centerInParent="true"
        android:progressDrawable="@drawable/circular"
        android:secondaryProgress="100"
        />

    <ImageView
        android:layout_width="90dp"
        android:layout_height="90dp"
        android:background="@drawable/whitecircle"
        android:layout_centerInParent="true"/>

    <TextView
        android:id="@+id/tv"
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:gravity="center"
        android:text="25%"
        android:layout_centerInParent="true"
        android:textColor="@color/colorPrimaryDark"
        android:textSize="20sp" />

</RelativeLayout>

In activity_main.xml I have used one circular image with white background to show white background around percentage. Here is the image:

You can change color of this image to set custom color around percentage text.

Now finally add following code to MainActivity.java :

import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.animation.DecelerateInterpolator;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    int pStatus = 0;
    private Handler handler = new Handler();
    TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Resources res = getResources();
        Drawable drawable = res.getDrawable(R.drawable.circular);
        final ProgressBar mProgress = (ProgressBar) findViewById(R.id.circularProgressbar);
        mProgress.setProgress(0);   // Main Progress
        mProgress.setSecondaryProgress(100); // Secondary Progress
        mProgress.setMax(100); // Maximum Progress
        mProgress.setProgressDrawable(drawable);

      /*  ObjectAnimator animation = ObjectAnimator.ofInt(mProgress, "progress", 0, 100);
        animation.setDuration(50000);
        animation.setInterpolator(new DecelerateInterpolator());
        animation.start();*/

        tv = (TextView) findViewById(R.id.tv);
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (pStatus < 100) {
                    pStatus += 1;

                    handler.post(new Runnable() {

                        @Override
                        public void run() {
                            // TODO Auto-generated method stub
                            mProgress.setProgress(pStatus);
                            tv.setText(pStatus + "%");

                        }
                    });
                    try {
                        // Sleep for 200 milliseconds.
                        // Just to display the progress slowly
                        Thread.sleep(8); //thread will take approx 1.5 seconds to finish
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

If you want to make horizontal progressbar, follow this link, it has many valuable examples with source code:
http://www.skholingua.com/android-basic/user-interface/form-widgets/progressbar



回答4:

Thanks to @Zeba I got my answer. For people having the same problem here is the updated circular_progress_bar.xml

<?xml version="1.0" encoding="utf-8"?>

<item android:id="@android:id/progress">
        <shape
            android:innerRadiusRatio="2.5"
            android:shape="ring"
            android:thicknessRatio="25.0" >
            <gradient
                android:angle="120"
                android:centerColor="@color/gray"
                android:endColor="@color/gray"
                android:startColor="@color/gray"
                android:type="sweep" />
        </shape>
</item>
<item android:id="@android:id/secondaryProgress">
    <rotate
        android:fromDegrees="270"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="270" >
        <shape
            android:innerRadiusRatio="2.5"
            android:shape="ring"
            android:thicknessRatio="25.0" >
            <gradient
                android:angle="120"
                android:centerColor="@color/green"
                android:endColor="@color/green"
                android:startColor="@color/green"
                android:type="sweep" />
        </shape>
    </rotate>
</item>



回答5:

A more simple solution I found is rotating the view 270 degrees, setting the inner text to transparent and setting new TextView on top of the circular progress bar with your data-

<FrameLayout
    android:id="@+id/linearLayout5"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.github.lzyzsd.circleprogress.DonutProgress
        android:id="@+id/donut_progress_lodging"
        android:layout_width="90dp"
        android:layout_height="90dp"
        android:layout_gravity="left|top"
        android:layout_marginLeft="30dp"
        app:donut_text_color="@color/tw__transparent"
        android:rotation="270"
        app:donut_finished_color="#34c6f1"
        app:donut_finished_stroke_width="5dp"
        app:donut_unfinished_color="#276894"
        app:donut_unfinished_stroke_width="5dp" />

  <TextView
        android:layout_width="40dp"
        android:layout_height="wrap_content"
        android:text="0%"
        android:textColor="#ffffff"
        android:layout_marginLeft="55dp"
        android:layout_marginBottom="10dp"
        android:textAlignment="center"
        android:id="@+id/textView_percentage_lodging"
        android:layout_gravity="left|center_vertical" />

</FrameLayout>


回答6:

A simple solution for rotating any view by some angle is giving rotation in XML.

<ProgressBar
      android:id="@+id/progress_bar"
      style="?android:attr/progressBarStyleHorizontal"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:max="100"
      android:progress="0"
      android:rotation="-90"
      android:progressDrawable="@drawable/circular" />