Custom Circular Progress Bar
package com.example.macbook.spinner; import android.content.res.Resources; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.ProgressBar; import android.widget.TextView; public class MainActivity extends AppCompatActivity { int pStatus = 0; private Handler handler = new Handler(); TextView tv; CircularProgressBar circularProgressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); circularProgressBar = (CircularProgressBar) findViewById(R.id.circularProgress); circularProgressBar.setProgressColor(Color.BLUE); 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 circularProgressBar.setProgress(pStatus); if(pStatus>70){ circularProgressBar.setProgressColor(Color.RED); }else{ circularProgressBar.setProgressColor(Color.BLUE); } tv.setText(pStatus + "%"); } }); try { // Sleep for 200 milliseconds. // Just to display the progress slowly Thread.sleep(30); //thread will take approx 1.5 seconds to finish } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <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="wrap_content" android:background="#FFFFFF" tools:context="com.example.parsaniahardik.progressanimation.MainActivity"> <com.example.macbook.spinner.CircularProgressBar android:id="@+id/circularProgress" android:layout_width="180dp" android:layout_marginLeft="10dp" android:layout_centerInParent="true" android:layout_height="180dp" /> <TextView android:visibility="visible" android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="25%" android:layout_centerInParent="true" android:textColor="@color/colorPrimaryDark" android:textSize="20sp" /> </RelativeLayout> </android.support.constraint.ConstraintLayout>CircularProgressBar.javapackage com.example.macbook.spinner; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; import android.view.animation.DecelerateInterpolator; public class CircularProgressBar extends View { private int mViewWidth; private int mViewHeight; private final float mStartAngle = -90; // Always start from top (default is: "3 o'clock on a watch.") private float mSweepAngle = 0; // How long to sweep from mStartAngle private float mSweepFinisher = 0; private float mMaxSweepAngle = 360; // Max degrees to sweep = full circle private int mStrokeWidth = 40; // Width of outline private int mAnimationDuration = 400; // Animation duration for progress change private int mMaxProgress = 100; // Max progress to use private boolean mDrawText = true; // Set to true if progress text should be drawn private boolean mRoundedCorners = true; // Set to true if rounded corners should be applied to outline ends private int mProgressColor = Color.BLACK; // Outline color private int mTextColor = Color.BLACK; // Progress text color private final Paint mPaint; // Allocate paint outside onDraw to avoid unnecessary object creation public CircularProgressBar(Context context) { this(context, null); } public CircularProgressBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircularProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); initMeasurments(); drawOutlineArc(canvas); // if (mDrawText) {// drawText(canvas);// } } private void initMeasurments() { mViewWidth = getWidth(); mViewHeight = getHeight(); } private void drawOutlineArc(Canvas canvas) { final int diameter = Math.min(mViewWidth, mViewHeight) - (mStrokeWidth); //Draw background mPaint.setColor(Color.GRAY); final RectF outerOval = new RectF(mStrokeWidth, mStrokeWidth, diameter, diameter); canvas.drawArc(outerOval, -90, 360, false, mPaint); mPaint.setColor(mProgressColor); mPaint.setStrokeWidth(mStrokeWidth); mPaint.setAntiAlias(true); mPaint.setStrokeCap(Paint.Cap.BUTT); mPaint.setStyle(Paint.Style.STROKE); if(mSweepAngle!=360) { canvas.drawArc(outerOval, mStartAngle, mSweepAngle - 5, false, mPaint); }else{ canvas.drawArc(outerOval, mStartAngle, mSweepAngle, false, mPaint); } mPaint.setColor(mProgressColor); mPaint.setStrokeWidth(mStrokeWidth); mPaint.setAntiAlias(true); mPaint.setStrokeCap(mRoundedCorners ? Paint.Cap.ROUND : Paint.Cap.BUTT); mPaint.setStyle(Paint.Style.STROKE); canvas.drawArc(outerOval, mStartAngle+5, mSweepAngle-8, false, mPaint); } // private void drawText(Canvas canvas) {// mPaint.setTextSize(Math.min(mViewWidth, mViewHeight) / 5f);// mPaint.setTextAlign(Paint.Align.CENTER);// mPaint.setStrokeWidth(0);// mPaint.setColor(mTextColor);//// // Center text// int xPos = (canvas.getWidth() / 2);// int yPos = (int) ((canvas.getHeight() / 2) - ((mPaint.descent() + mPaint.ascent()) / 2)) ;//// canvas.drawText(calcProgressFromSweepAngle(mSweepAngle) + "%", xPos, yPos, mPaint);// } private float calcSweepAngleFromProgress(int progress) { return (mMaxSweepAngle / mMaxProgress) * progress; } private int calcProgressFromSweepAngle(float sweepAngle) { return (int) ((sweepAngle * mMaxProgress) / mMaxSweepAngle); } /** * Set progress of the circular progress bar. * @param progress progress between 0 and 100. */ public void setProgress(int progress) { ValueAnimator animator = ValueAnimator.ofFloat(mSweepAngle, calcSweepAngleFromProgress(progress)); animator.setInterpolator(new DecelerateInterpolator()); animator.setDuration(mAnimationDuration); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { mSweepAngle = (float) valueAnimator.getAnimatedValue(); invalidate(); } }); animator.start(); } public void setProgressColor(int color) { mProgressColor = color; invalidate(); } public void setProgressWidth(int width) { mStrokeWidth = width; invalidate(); } public void setTextColor(int color) { mTextColor = color; invalidate(); } public void showProgressText(boolean show) { mDrawText = show; invalidate(); } /** * Toggle this if you don't want rounded corners on progress bar. * Default is true. * @param roundedCorners true if you want rounded corners of false otherwise. */ public void useRoundedCorners(boolean roundedCorners) { mRoundedCorners = roundedCorners; invalidate(); } }OutPut