package com.marshalchen.common.ui;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.View;
import com.marshalchen.common.R;
public class ExpandedCircleProgressView extends View {
private static final String TAG = "ExpandedCircleProgressView";
private class Circle {
float radius;
float centerX;
float centerY;
Circle(float x, float y, float innerCircleSize) {
this.radius = innerCircleSize;
this.centerX = x;
this.centerY = y;
}
}
private Paint mProgressCirclePaint;
private Circle mProgressCircle;
private Paint mInnerCirclePaint;
private Circle mInnerCircle;
private Paint mTextPaint;
private String mCurrentProgress = "0%";
private Paint mOuterCirclePaint;
private Circle mOuterCircle;
private static int SLEEP_TIME = 8;
private static float INCRESING_SIZE = 4;
private ProgressUpdateTask mUpdateTask;
private float mInnerCircleSize;
private float mOuterCircleSize;
private int mInnerCircleColor;
private int mOuterCircleColor;
private int mProgressCircleColor;
private int mTextProgressColor;
private float mOuterCircleLineWidth;
private float mTextSize;
private final static int MAX_PROGRESS = 100;
public ExpandedCircleProgressView(final Context context) {
super(context);
init(context, null);
}
public ExpandedCircleProgressView(final Context context,
final AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ExpandedCircleProgressView(final Context context,
final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
public void init(final Context context, AttributeSet attrs) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.ExpandedCircleProgressView, 0, 0);
try {
// Retrieve the values from the TypedArray and store into
// fields of this class.
mInnerCircleSize = a.getDimension(
R.styleable.ExpandedCircleProgressView_innerCircleSize,
0.0f);
mOuterCircleSize = a.getDimension(
R.styleable.ExpandedCircleProgressView_outerCircleSize,
0.0f);
mInnerCircleColor = a.getColor(
R.styleable.ExpandedCircleProgressView_innerCircleColor,
0xff000000);
mOuterCircleColor = a.getColor(
R.styleable.ExpandedCircleProgressView_outerCircleColor,
0xff000000);
mProgressCircleColor = a.getColor(
R.styleable.ExpandedCircleProgressView_progressCircleColor,
0xff000000);
mOuterCircleLineWidth = a
.getDimension(
R.styleable.ExpandedCircleProgressView_outerCircleLineWidth,
0.5f);
mTextSize = a.getDimension(
R.styleable.ExpandedCircleProgressView_textProgressSize,
0.0f);
mTextProgressColor = a.getColor(
R.styleable.ExpandedCircleProgressView_textProgressColor,
0xff000000);
} finally {
// release the TypedArray so that it can be reused.
a.recycle();
}
INCRESING_SIZE = (mOuterCircleSize - mInnerCircleSize) / 100;
SLEEP_TIME = (int) (INCRESING_SIZE * 1500 / mOuterCircleSize);
mProgressCirclePaint = new Paint();
mProgressCirclePaint.setColor(mProgressCircleColor);
mProgressCirclePaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mProgressCirclePaint.setStyle(Paint.Style.FILL);
mInnerCirclePaint = new Paint();
mInnerCirclePaint.setColor(mInnerCircleColor);
mInnerCirclePaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mInnerCirclePaint.setStyle(Paint.Style.FILL);
mOuterCirclePaint = new Paint();
mOuterCirclePaint.setColor(mOuterCircleColor);
mOuterCirclePaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mOuterCirclePaint.setStrokeWidth(mOuterCircleLineWidth);
mOuterCirclePaint.setStyle(Paint.Style.STROKE);
mTextPaint = new Paint();
mTextPaint.setColor(mTextProgressColor);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTextSize(mTextSize);
cancelUpdateTask();
}
/**
* Set size of the inner circle
* @param size size of the inner circle
*/
public void setInnerCircleSize(int size){
mInnerCircleSize = size;
INCRESING_SIZE = (mOuterCircleSize - mInnerCircleSize) / 100;
}
/**
* Set size of the outer circle
* @param size size of the outer circle
*/
public void setOuterCircleSize(int size){
mOuterCircleSize = size;
INCRESING_SIZE = (mOuterCircleSize - mInnerCircleSize) / 100;
SLEEP_TIME = (int) (INCRESING_SIZE * 1500 / mOuterCircleSize);
}
/**
* Set color of the inner circle
* @param color color of the inner circle
*/
public void setInnerCircleColor(int color) {
mInnerCircleColor = color;
}
/**
* Set color of the outer circle
* @param color color of the outer circle
*/
public void setOuterCircleColor(int color) {
mOuterCircleColor = color;
}
/**
* Set color of the progress text
* @param color color of the progress text
*/
public void setProgressTextColor(int color) {
mTextProgressColor = color;
}
/**
* Set color of circle of expanding progress
* @param color color of circle of expanding progress
*/
public void setProgresColor(int color) {
mProgressCircleColor = color;
}
/**
* Set width of the outer circle line
* @param width width of the outer circle line
*/
public void setOuterCircleLineWidth(int width) {
mOuterCircleLineWidth = width;
}
/**
* Set size of the progress text
* @param size size of the progress text
*/
public void setTextProgressSize(int size) {
mTextSize = size;
}
/**
* get maximum value of progress
* @return maximum value of progress
*/
public int getMaxProgress() {
return MAX_PROGRESS;
}
/**
* set current progress
* @param progress set progress from 0 to max progress(100)
*/
public void setProgress(int progress) {
if (mUpdateTask != null)
mUpdateTask.cancel(true);
if (progress > MAX_PROGRESS)
return;
int size = (int) (progress * INCRESING_SIZE + mInnerCircleSize);
mUpdateTask = new ProgressUpdateTask();
mUpdateTask.execute(progress, size);
}
@Override
public void onDraw(final Canvas canvas) {
canvas.drawCircle(mProgressCircle.centerX, mProgressCircle.centerY,
mProgressCircle.radius, mProgressCirclePaint);
canvas.drawCircle(mInnerCircle.centerX, mInnerCircle.centerY,
mInnerCircle.radius, mInnerCirclePaint);
canvas.drawCircle(mOuterCircle.centerX, mOuterCircle.centerY,
mOuterCircle.radius, mOuterCirclePaint);
canvas.drawText(mCurrentProgress, mInnerCircle.centerX,
mInnerCircle.centerY, mTextPaint);
}
@Override
protected void onMeasure(final int widthMeasureSpec,
final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
int x = w / 2;
int y = h / 2;
mProgressCircle = new Circle(x, y, mInnerCircleSize);
mInnerCircle = new Circle(x, y, mInnerCircleSize);
mOuterCircle = new Circle(x, y, mOuterCircleSize);
}
public class ProgressUpdateTask extends
AsyncTask<Integer, Integer, Integer> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Integer doInBackground(Integer... params) {
if (mProgressCircle == null)
return null;
int progress = params[0];
int size = params[1];
if (progress >= 100)
progress = 100;
boolean isIncresing = mProgressCircle.radius <= size;
while (continueLoop(isIncresing, size)) {
// exit loop if asynctask is cancelled
if (isCancelled())
break;
if (isIncresing)
mProgressCircle.radius += INCRESING_SIZE;
else
mProgressCircle.radius -= INCRESING_SIZE;
publishProgress(progress);
try {
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return progress;
}
private boolean continueLoop(boolean isIncresing, int size) {
if (isIncresing)
return mProgressCircle.radius <= size;
else
return mProgressCircle.radius >= size;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
int value = values[0];
mCurrentProgress = value + "%";
invalidate();
}
@Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
if (result != null)
mCurrentProgress = result + "%";
}
}
/**
* Cancel updating progress task
*/
public void cancelUpdateTask() {
if (mUpdateTask != null)
mUpdateTask.cancel(true);
}
}