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.


package com.androidgreeve.circularprogress;

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

/*

  Class used to show a determinate progress indicator.

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

 */

class ProgressIndicator 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 = new PorterDuffXfermode(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;

    public ProgressIndicator(Context context) {
        this(context, null);
    }

    public ProgressIndicator(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 void setForegroundColor(int color) {
        this.mColorForeground = color;
        mPaintForeground.setColor(color);
        invalidate();
    }
   
   public void setBackgroundColor(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);
 

Facebook Messenger like profile image crop in android

Lots of our reader send me email asking for how to crop image as in google plus app and facebook messanger profile image in circle.So I decided to put this tutorial live on how you can crop that imageview in circle.

There are more ways of doing it I got this using the canvas elements on the android.The android bitmap can be used to align,stretch,and lots more.The Android bitmapdrawable give a lots of flexibilty to attain image crop.

Some inspiration of what we are trying to build is somthing like this:
 
Above is the Image of facebook messanger .The profile image here is cropped to circle.This is what we are going to develop.

Lets start creating.

1.Create New ProjectNew->Android Application Project.
2.Create New Class file RoundprofImage.java 
Right Click on package com.androidgreeve.profile.roundimage ->New->RoundprofImage.java
3.Copy the below code in roundimage.java file
package com.androidgreeve.profile.roundimage
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
public class RoundImage extends Drawable {
      private final Bitmap mBitmap;
      private final Paint mPaint;
      private final RectF mRectF;
      private final int mBitmapWidth;
      private final int mBitmapHeight;
      public RoundImage(Bitmap bitmap) {
            mBitmap = bitmap;
            mRectF = new RectF();
            mPaint = new Paint();
            mPaint.setAntiAlias(true);
            mPaint.setDither(true);
            final BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            mPaint.setShader(shader);
            mBitmapWidth = mBitmap.getWidth();
            mBitmapHeight = mBitmap.getHeight();
      }
      @Override
      public void draw(Canvas canvas) {
            canvas.drawOval(mRectF, mPaint);
      }
      @Override
      protected void onBoundsChange(Rect bounds) {
            super.onBoundsChange(bounds);
            mRectF.set(bounds);
      }
      @Override
      public void setAlpha(int alpha) {
            if (mPaint.getAlpha() != alpha) {
                  mPaint.setAlpha(alpha);
                  invalidateSelf();
            }
      }
      @Override
      public void setColorFilter(ColorFilter cf) {
            mPaint.setColorFilter(cf);
      }
      @Override
      public int getOpacity() {
            return PixelFormat.TRANSLUCENT;
      }
      @Override
      public int getIntrinsicWidth() {
            return mBitmapWidth;
      }
      @Override
      public int getIntrinsicHeight() {
            return mBitmapHeight;
      }
      public void setAntiAlias(boolean aa) {
            mPaint.setAntiAlias(aa);
            invalidateSelf();
      }
      @Override
      public void setFilterBitmap(boolean filter) {
            mPaint.setFilterBitmap(filter);
            invalidateSelf();
      }
      @Override
      public void setDither(boolean dither) {
            mPaint.setDither(dither);
            invalidateSelf();
      }
      public Bitmap getBitmap() {
            return mBitmap;
      }

}

Now you can add the image view in activity_main.xml file.copy the following code in it.
Activity_main .xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000"
    android:orientation="vertical" >
    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:scaleType="centerCrop"
        android:layout_gravity="center"
        android:src="@drawable/image" />
<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="@string/Androidgreeve"/>
 

</LinearLayout>
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;
import com.androidgree.profile.roundprofimage.R;
public class MainActivity extends Activity {
      ImageView imageView1;
      RoundImage roundedImage;
      @Override
      protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            imageView1 = (ImageView) findViewById(R.id.imageView1);
            Bitmap bm = BitmapFactory.decodeResource(getResources(),R.drawable.image);
            roundedImage = new RoundImage(bm);
            imageView1.setImageDrawable(roundedImage);
      }
}
Run the project .All is done now!
Hope you find easier to understand the code.Please Comment your views
Sponsor:
Do miss out to check out the offer of the month post! we already started gifting the Ebooks.