Create custom circular progressbar in android

A tutorial on how to create the page preloading effect seen on the android app. We are going to use .The circular progress bar is used as an buffer element in most of the app.

Today we want to show you how to create a very simplepage preloading effect for android . For an android app, where it’s crucial to load all or part of the assets, these kind of progressbar can be made use of.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
 android:background="@color/skyblue">
//Demo 1
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="horizontal" >

            <com.androidgreeve.circularprogress.ProgressIndicator
                android:id="@+id/determinate_progress_indicator1"
                android:layout_width="100dp"
                android:layout_height="100dp" />

            <com.androidgreeve.circularprogress.Progressndicator
                android:id="@+id/determinate_progress_indicator2"
                android:layout_width="100dp"
                android:layout_height="100dp" />

            <com.androidgreeve.circularprogress.ProgressIndicator
                android:id="@+id/determinate_progress_indicator3"
                android:layout_width="100dp"
                android:layout_height="100dp" />
        </LinearLayout>


//Demo2 Layout
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="horizontal" >

            <com.androidgreeve.circularprogress.ProgressIndicator
                android:id="@+id/determinate_progress_indicator4"
                android:layout_width="100dp"
                android:layout_height="100dp" />

            <com.androidgreeve.circularprogress.ProgressIndicator
                android:id="@+id/determinate_progress_indicator5"
                android:layout_width="100dp"
                android:layout_height="100dp" />

            <com.androidgreeve.circularprogress.ProgressIndicator
                android:id="@+id/determinate_progress_indicator6"
                android:layout_width="100dp"
                android:layout_height="100dp" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

2) Now we are going thtrough to the java file to add the progress elements
First, we will create a ProgressIndicator.java class which will extends View class. 
This class is used for showing Progressbar.


packagecom.androidgreeve.circularprogress;

importandroid.content.Context;
importandroid.content.res.Resources;
importandroid.graphics.Bitmap;
importandroid.graphics.Canvas;
importandroid.graphics.Color;
importandroid.graphics.Paint;
importandroid.graphics.PorterDuff;
importandroid.graphics.PorterDuffXfermode;
importandroid.graphics.RectF;
importandroid.graphics.Xfermode;
importandroid.util.AttributeSet;
importandroid.view.View;

/*

  Class used to show a determinate progress indicator.

  Two display modes are supported "wheel" and "pie"

 */

classProgressIndicator extends View {
    private final RectF mRect = new RectF();
    private final RectF mRectInner = new RectF();
    private final Paint mPaintForeground = new Paint();
    private final Paint mPaintBackground = new Paint();
    private final Paint mPaintErase = new Paint();
    private static final Xfermode PORTER_DUFF_CLEAR = newPorterDuffXfermode(PorterDuff.Mode.CLEAR);
    private int mColorForeground = Color.WHITE;
    private int mColorBackground = Color.BLACK;
    private float mValue;
    private boolean mPieStyle;
    /*

      Value which makes our custom drawn indicator have roughly the same size

      as the built-in ProgressBar indicator.

     */

    private static final float PADDING = 4;
    private float mPadding;
    private Bitmap mBitmap;
    /**

     Value which makes our custom drawn indicator have roughly the same

     thickness as the built-in ProgressBar indicator.

     */

    private static final float INNER_RADIUS_RATIO = 0.84f;

    publicProgressIndicator(Context context) {
        this(context, null);
    }

    publicProgressIndicator(Context context, AttributeSet attrs) {
        super(context, attrs);
        Resources r = context.getResources();
        float scale = r.getDisplayMetrics().density;
        mPadding = scale * PADDING ;
        mPaintForeground.setColor(mColorForeground);
        mPaintForeground.setAntiAlias(true);
        mPaintBackground.setColor(mColorBackground);
        mPaintBackground.setAntiAlias(true);
        mPaintErase.setXfermode(PORTER_DUFF_CLEAR);
        mPaintErase.setAntiAlias(true);
    }

    /*

      Set the style of this indicator.The two supported styles are "wheel" and "pie"

      @param style One of {@link STYLE_WHEEL} or {@link STYLE_PIE}

     */

    public void setPieStyle(boolean pieStyle) {
        if (mPieStyle == pieStyle) {
            return;
        }
        mPieStyle = pieStyle;
        updateBitmap();
    }

    /*

      Return the current style of this indicator.

           */

    public boolean getIsPieStyle() {
        return mPieStyle;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(mBitmap, getWidth() / 2 - mBitmap.getWidth() / 2,
                          getHeight() / 2 - mBitmap.getHeight() / 2, null);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        float bitmapWidth = w - 2 * mPadding;
        float bitmapHeight = h - 2 * mPadding;
        float radius = Math.min(bitmapWidth / 2, bitmapHeight / 2);
        mRect.set(0, 0, bitmapWidth, bitmapHeight);
        radius *= INNER_RADIUS_RATIO;
        mRectInner.set(bitmapWidth / 2f - radius, bitmapHeight / 2f - radius, bitmapWidth / 2f + radius, bitmapHeight / 2f + radius);
        updateBitmap();
    }

   public voidsetForegroundColor(int color) {
        this.mColorForeground = color;
        mPaintForeground.setColor(color);
        invalidate();
    }
   
   public voidsetBackgroundColor(int color) {
        this.mColorBackground = color;
        mPaintBackground.setColor(color);
        invalidate();
    }

    public synchronized void setValue(float value) {
        mValue = value;
        updateBitmap();
    }

    private void updateBitmap() {
        if (mRect == null || mRect.width() == 0) {
            return;
        }
        mBitmap = Bitmap.createBitmap((int) mRect.width(), (int) mRect.height(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mBitmap);
        canvas.drawArc(mRect, -90, 360, true, mPaintBackground);
        if (mValue < 0.01f) {
            canvas.drawLine(mRect.width() / 2, mRect.height() / 2, mRect.width() / 2, 0, mPaintForeground);
        }
        float angle = mValue * 360;
        canvas.drawArc(mRect, -90, angle, true, mPaintForeground);
        if (!mPieStyle) {
            canvas.drawArc(mRectInner, -90, 360, true, mPaintErase);
        }
        postInvalidate();
    }
}
// @return <tt>True</tt> if the indicator has the "pie" style


The Mainactivity contains the mapping between the progressbar and the xml file
Demo1_activity.java

package com.androidgreeve.circularprogress;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class Demo_Activity extends Activity{

      ProgressIndicator mProgressIndicator1,mProgressIndicator2, mProgressIndicator3,
      Button btnreset;
      float max = 1;
      float update = 0;
      boolean threadRunning = false;;
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mProgressIndicator1 = (ProgressIndicator) findViewById(R.id.determinate_progress_indicator1);
            mProgressIndicator2 = (ProgressIndicator) findViewById(R.id.determinate_progress_indicator2);
            mProgressIndicator3 = (ProgressIndicator) findViewById(R.id.determinate_progress_indicator3);
            mProgressIndicator4 = (ProgressIndicator) findViewById(R.id.determinate_progress_indicator4);
            mProgressIndicator5 = (ProgressIndicator) findViewById(R.id.determinate_progress_indicator5);
            mProgressIndicator6 = (ProgressIndicator) findViewById(R.id.determinate_progress_indicator6);
            btnreset = (Button) findViewById(R.id.btnreset);
          
            mProgressIndicator1.setForegroundColor(Color.parseColor("#9D5858"));
            mProgressIndicator1.setBackgroundColor(Color.parseColor("#E40DAA"));
      
        mProgressIndicator2.setForegroundColor(Color.parseColor("#E40DAA"));
        mProgressIndicator2.setBackgroundColor(Color.parseColor("#f48fb1"));
      
        mProgressIndicator3.setForegroundColor(Color.parseColor("#5BE40D"));
        mProgressIndicator3.setBackgroundColor(Color.parseColor("#ce93d8"));
      
       
        startThread();
            btnreset.setOnClickListener(new OnClickListener() {
                  @Override
                  public void onClick(View v) {
                        if(threadRunning)
                              return;
                        startThread();
                  }
            });
      }
    
      private void startThread() {
            new Thread(new Runnable() {
                  @Override
                  public void run() {
                        threadRunning = true;
                        update = 0;
                        while(update <= max){
                              update += 0.005;
                          updateProgressIndicatorValue();
                          try{
                              Thread.sleep(100);
                          }catch(Exception e){
                            
                          }
                        }
                        threadRunning = false;
                  }
            }).start();
      }
    
   private void updateProgressIndicatorValue() {
         this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
              mProgressIndicator1.setValue(update);
              mProgressIndicator2.setValue(update);
              mProgressIndicator3.setValue(update);
             
            }
         });
    }
}
 
Similarly for demo2_activity changes to be made are:
A)mProgressIndicator4,mProgressIndicator5,mProgressIndicator6;
B)mProgressIndicator4.setForegroundColor(Color.parseColor("#CCC000"));
        mProgressIndicator4.setBackgroundColor(Color.parseColor("#aCbfff"));
        mProgressIndicator4.setPieStyle(true);
      
        mProgressIndicator5.setForegroundColor(Color.parseColor("#FAFFAF"));
        mProgressIndicator5.setBackgroundColor(Color.parseColor("#80cbc4"));
        mProgressIndicator5.setPieStyle(true);
      
        mProgressIndicator6.setForegroundColor(Color.parseColor("#0d5302"));
        mProgressIndicator6.setBackgroundColor(Color.parseColor("#72d572"));
        mProgressIndicator6.setPieStyle(true);
       

 C)     mProgressIndicator4.setValue(update);
        mProgressIndicator5.setValue(update);
        mProgressIndicator6.setValue(update);
 

Hey I'm Venkat
Developer, Blogger, Thinker and Data scientist. nintyzeros [at] gmail.com I love the Data and Problem - An Indian Lives in US .If you have any question do reach me out via below social media

4 comments

Your tutorials are very nice and kept very simple.But why can't u just upload that code to server so that it would be more helpful.

A1 Awesome stuff man.. Nice post .Nice design and color combination . Thank u

Very nice .. It worked for me.. Thank u

Very useful!
I was working on a plain progress bar and I did not know how to draw it but this blog
entry made me do a similar onDraw method
Thanks a lot!


EmoticonEmoticon