Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android : Semi Circle Progress Bar

Tags:

I want semi circle progress bar in background of image. just like below image.

enter image description here

i have tried to draw using canvas but can't get success. i have also tired some custom progress bar library but result is same.

any suggestions.

looking for one time development and used in every screen size.

like image 473
Dhaval Parmar Avatar asked Mar 19 '14 08:03

Dhaval Parmar


People also ask

How do you make a circle in progress bar?

Step 1: First, we will design a basic progress bar structure using HTML. First, we will create a container div that holds both progress bars. After that, we will create another div inside the container div that creates the circular div element.

What are types of progress bar in android?

Progress bar supports two modes to represent progress: determinate, and indeterminate. For a visual overview of the difference between determinate and indeterminate progress modes, see Progress & activity.


1 Answers

This can be implemented by clipping a canvas containing an image at an angle (By drawing an arc).

You can use an image something like this

enter image description here

And clip that image by drawing an arc.

Here is how you can do it.

//Convert the progress in range of 0 to 100 to angle in range of 0 180. Easy math. float angle = (progress * 180) / 100; mClippingPath.reset(); //Define a rectangle containing the image RectF oval = new RectF(mPivotX, mPivotY, mPivotX + mBitmap.getWidth(), mPivotY + mBitmap.getHeight()); //Move the current position to center of rect mClippingPath.moveTo(oval.centerX(), oval.centerY()); //Draw an arc from center to given angle mClippingPath.addArc(oval, 180, angle); //Draw a line from end of arc to center mClippingPath.lineTo(oval.centerX(), oval.centerY()); 

And once you get the path, you can use clipPath function to clip the canvas in that path.

canvas.clipPath(mClippingPath); 

Here is the Complete code

SemiCircleProgressBarView.java

import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Path; import android.graphics.RectF; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.View;    public class SemiCircleProgressBarView extends View {      private Path mClippingPath;     private Context mContext;     private Bitmap mBitmap;     private float mPivotX;     private float mPivotY;      public SemiCircleProgressBarView(Context context) {         super(context);         mContext = context;         initilizeImage();     }      public SemiCircleProgressBarView(Context context, AttributeSet attrs) {         super(context, attrs);         mContext = context;         initilizeImage();     }      private void initilizeImage() {         mClippingPath = new Path();          //Top left coordinates of image. Give appropriate values depending on the position you wnat image to be placed         mPivotX = getScreenGridUnit();         mPivotY = 0;          //Adjust the image size to support different screen sizes         Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.circle);         int imageWidth = (int) (getScreenGridUnit() * 30);         int imageHeight = (int) (getScreenGridUnit() * 30);         mBitmap = Bitmap.createScaledBitmap(bitmap, imageWidth, imageHeight, false);     }      public void setClipping(float progress) {          //Convert the progress in range of 0 to 100 to angle in range of 0 180. Easy math.         float angle = (progress * 180) / 100;         mClippingPath.reset();         //Define a rectangle containing the image         RectF oval = new RectF(mPivotX, mPivotY, mPivotX + mBitmap.getWidth(), mPivotY + mBitmap.getHeight());         //Move the current position to center of rect         mClippingPath.moveTo(oval.centerX(), oval.centerY());         //Draw an arc from center to given angle         mClippingPath.addArc(oval, 180, angle);         //Draw a line from end of arc to center         mClippingPath.lineTo(oval.centerX(), oval.centerY());         //Redraw the canvas         invalidate();     }      @Override     protected void onDraw(Canvas canvas) {         super.onDraw(canvas);          //Clip the canvas         canvas.clipPath(mClippingPath);         canvas.drawBitmap(mBitmap, mPivotX, mPivotY, null);      }      private float getScreenGridUnit() {         DisplayMetrics metrics = new DisplayMetrics();         ((Activity)mContext).getWindowManager().getDefaultDisplay().getMetrics(metrics);         return metrics.widthPixels / 32;     }  } 

And using it in any activity is very easy.

activity_main.xml

<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"     tools:context=".MainActivity" >      <com.example.progressbardemo.SemiCircleProgressBarView         android:id="@+id/progress"         android:layout_width="match_parent"         android:layout_height="match_parent" />  </RelativeLayout>    

Note that clipPath function doesn't work if the hardware acceleration is turned on. You can turn off the hardware acceleration only for that view.

   //Turn off hardware accleration   semiCircleProgressBarView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); 

MainActivity.java

public class MainActivity extends Activity {      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);          SemiCircleProgressBarView semiCircleProgressBarView = (SemiCircleProgressBarView) findViewById(R.id.progress);         semiCircleProgressBarView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);          semiCircleProgressBarView.setClipping(70);     }  }   

As and when the progress changes you can set the progressbar by calling function,

semiCircleProgressBarView.setClipping(progress); 

Ex: semiCircleProgressBarView.setClipping(50); //50% progress

enter image description here

semiCircleProgressBarView.setClipping(70); //70% progress 

enter image description here

You can use your own Image to match the requirements. Hope it helps!!

Edit : To move the semi circle to bottom of the screen, change mPivotY value. Something like this

//In `SemiCircleProgressBarView.java` //We don't get the canvas width and height initially, set `mPivoyY` inside `onWindowFocusChanged` since `getHeight` returns proper results by that time         public void onWindowFocusChanged(boolean hasWindowFocus) {             super.onWindowFocusChanged(hasWindowFocus);              mPivotX = getScreenGridUnit();             mPivotY = getHeight() - (mBitmap.getHeight() / 2);         } 
like image 113
Abhishek V Avatar answered Dec 14 '22 08:12

Abhishek V