package com.github.lzyzsd.circleprogress;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by bruce on 14-10-30.
*/
public class DonutProgress extends View {
private Paint finishedPaint;
private Paint unfinishedPaint;
private Paint innerCirclePaint;
protected Paint textPaint;
private RectF finishedOuterRect = new RectF();
private RectF unfinishedOuterRect = new RectF();
private float textSize;
private int textColor;
private int progress = 0;
private int max;
private int finishedStrokeColor;
private int unfinishedStrokeColor;
private float finishedStrokeWidth;
private float unfinishedStrokeWidth;
private int innerBackgroundColor;
private String prefixText = "";
private String suffixText = "%";
private final float default_stroke_width;
private final int default_finished_color = Color.rgb(66, 145, 241);
private final int default_unfinished_color = Color.rgb(204, 204, 204);
private final int default_text_color = Color.rgb(66, 145, 241);
private final int default_inner_background_color = Color.TRANSPARENT;
private final int default_max = 100;
private final float default_text_size;
private final int min_size;
private static final String INSTANCE_STATE = "saved_instance";
private static final String INSTANCE_TEXT_COLOR = "text_color";
private static final String INSTANCE_TEXT_SIZE = "text_size";
private static final String INSTANCE_FINISHED_STROKE_COLOR = "finished_stroke_color";
private static final String INSTANCE_UNFINISHED_STROKE_COLOR = "unfinished_stroke_color";
private static final String INSTANCE_MAX = "max";
private static final String INSTANCE_PROGRESS = "progress";
private static final String INSTANCE_SUFFIX = "suffix";
private static final String INSTANCE_PREFIX = "prefix";
private static final String INSTANCE_FINISHED_STROKE_WIDTH = "finished_stroke_width";
private static final String INSTANCE_UNFINISHED_STROKE_WIDTH = "unfinished_stroke_width";
private static final String INSTANCE_BACKGROUND_COLOR = "inner_background_color";
public DonutProgress(Context context) {
this(context, null);
}
public DonutProgress(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DonutProgress(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
default_text_size = Utils.sp2px(getResources(), 18);
min_size = (int) Utils.dp2px(getResources(), 100);
default_stroke_width = Utils.dp2px(getResources(), 10);
final TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DonutProgress, defStyleAttr, 0);
initByAttributes(attributes);
attributes.recycle();
initPainters();
}
protected void initPainters() {
textPaint = new TextPaint();
textPaint.setColor(textColor);
textPaint.setTextSize(textSize);
textPaint.setAntiAlias(true);
finishedPaint = new Paint();
finishedPaint.setColor(finishedStrokeColor);
finishedPaint.setStyle(Paint.Style.STROKE);
finishedPaint.setAntiAlias(true);
finishedPaint.setStrokeWidth(finishedStrokeWidth);
unfinishedPaint = new Paint();
unfinishedPaint.setColor(unfinishedStrokeColor);
unfinishedPaint.setStyle(Paint.Style.STROKE);
unfinishedPaint.setAntiAlias(true);
unfinishedPaint.setStrokeWidth(unfinishedStrokeWidth);
innerCirclePaint = new Paint();
innerCirclePaint.setColor(innerBackgroundColor);
innerCirclePaint.setAntiAlias(true);
}
protected void initByAttributes(TypedArray attributes) {
finishedStrokeColor = attributes.getColor(R.styleable.DonutProgress_donut_finished_color, default_finished_color);
unfinishedStrokeColor = attributes.getColor(R.styleable.DonutProgress_donut_unfinished_color, default_unfinished_color);
textColor = attributes.getColor(R.styleable.DonutProgress_donut_text_color, default_text_color);
textSize = attributes.getDimension(R.styleable.DonutProgress_donut_text_size, default_text_size);
setMax(attributes.getInt(R.styleable.DonutProgress_donut_max, default_max));
setProgress(attributes.getInt(R.styleable.DonutProgress_donut_progress, 0));
finishedStrokeWidth = attributes.getDimension(R.styleable.DonutProgress_donut_finished_stroke_width, default_stroke_width);
unfinishedStrokeWidth = attributes.getDimension(R.styleable.DonutProgress_donut_unfinished_stroke_width, default_stroke_width);
if (attributes.getString(R.styleable.DonutProgress_donut_prefix_text) != null) {
prefixText = attributes.getString(R.styleable.DonutProgress_donut_prefix_text);
}
if (attributes.getString(R.styleable.DonutProgress_donut_suffix_text) != null) {
suffixText = attributes.getString(R.styleable.DonutProgress_donut_suffix_text);
}
innerBackgroundColor = attributes.getColor(R.styleable.DonutProgress_donut_background_color, default_inner_background_color);
}
@Override
public void invalidate() {
initPainters();
super.invalidate();
}
public float getFinishedStrokeWidth() {
return finishedStrokeWidth;
}
public void setFinishedStrokeWidth(float finishedStrokeWidth) {
this.finishedStrokeWidth = finishedStrokeWidth;
this.invalidate();
}
public float getUnfinishedStrokeWidth() {
return unfinishedStrokeWidth;
}
public void setUnfinishedStrokeWidth(float unfinishedStrokeWidth) {
this.unfinishedStrokeWidth = unfinishedStrokeWidth;
this.invalidate();
}
private float getProgressAngle() {
return getProgress() / (float) max * 360f;
}
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
this.progress = progress;
if (this.progress > getMax()) {
this.progress %= getMax();
}
invalidate();
}
public int getMax() {
return max;
}
public void setMax(int max) {
if (max > 0) {
this.max = max;
invalidate();
}
}
public float getTextSize() {
return textSize;
}
public void setTextSize(float textSize) {
this.textSize = textSize;
this.invalidate();
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
this.invalidate();
}
public int getFinishedStrokeColor() {
return finishedStrokeColor;
}
public void setFinishedStrokeColor(int finishedStrokeColor) {
this.finishedStrokeColor = finishedStrokeColor;
this.invalidate();
}
public int getUnfinishedStrokeColor() {
return unfinishedStrokeColor;
}
public void setUnfinishedStrokeColor(int unfinishedStrokeColor) {
this.unfinishedStrokeColor = unfinishedStrokeColor;
this.invalidate();
}
public String getSuffixText() {
return suffixText;
}
public void setSuffixText(String suffixText) {
this.suffixText = suffixText;
this.invalidate();
}
public String getPrefixText() {
return prefixText;
}
public void setPrefixText(String prefixText) {
this.prefixText = prefixText;
this.invalidate();
}
public int getInnerBackgroundColor() {
return innerBackgroundColor;
}
public void setInnerBackgroundColor(int innerBackgroundColor) {
this.innerBackgroundColor = innerBackgroundColor;
this.invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measure(widthMeasureSpec), measure(heightMeasureSpec));
}
private int measure(int measureSpec){
int result;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
if(mode == MeasureSpec.EXACTLY){
result = size;
}else{
result = min_size;
if(mode == MeasureSpec.AT_MOST){
result = Math.min(result, size);
}
}
return result;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (finishedStrokeWidth > unfinishedStrokeWidth) {
finishedOuterRect.set(finishedStrokeWidth / 2,
finishedStrokeWidth / 2,
getWidth() - finishedStrokeWidth / 2,
getHeight() - finishedStrokeWidth / 2);
float delta = (finishedStrokeWidth - unfinishedStrokeWidth) / 2f;
unfinishedOuterRect.set(unfinishedStrokeWidth / 2,
unfinishedStrokeWidth / 2,
getWidth() - unfinishedStrokeWidth / 2 - delta,
getHeight() - unfinishedStrokeWidth / 2 - delta);
} else {
float delta = (unfinishedStrokeWidth - finishedStrokeWidth) / 2f;
finishedOuterRect.set(finishedStrokeWidth / 2,
finishedStrokeWidth / 2,
getWidth() - finishedStrokeWidth / 2 - delta,
getHeight() - finishedStrokeWidth / 2 - delta);
unfinishedOuterRect.set(unfinishedStrokeWidth / 2,
unfinishedStrokeWidth / 2,
getWidth() - unfinishedStrokeWidth / 2,
getHeight() - unfinishedStrokeWidth / 2);
}
float innerCircleRadius = (getWidth() - Math.min(finishedStrokeWidth, unfinishedStrokeWidth) + Math.abs(finishedStrokeWidth - unfinishedStrokeWidth)) / 2f;
canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, innerCircleRadius, innerCirclePaint);
canvas.drawArc(finishedOuterRect, 0, getProgressAngle(), false, finishedPaint);
canvas.drawArc(unfinishedOuterRect, getProgressAngle(), 360 - getProgressAngle(), false, unfinishedPaint);
String text = prefixText + progress + suffixText;
if (!TextUtils.isEmpty(text)) {
float textHeight = textPaint.descent() + textPaint.ascent();
canvas.drawText(text, (getWidth() - textPaint.measureText(text)) / 2.0f, (getWidth() - textHeight) / 2.0f, textPaint);
}
}
@Override
protected Parcelable onSaveInstanceState() {
final Bundle bundle = new Bundle();
bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());
bundle.putInt(INSTANCE_TEXT_COLOR, getTextColor());
bundle.putFloat(INSTANCE_TEXT_SIZE, getTextSize());
bundle.putInt(INSTANCE_FINISHED_STROKE_COLOR, getFinishedStrokeColor());
bundle.putInt(INSTANCE_UNFINISHED_STROKE_COLOR, getUnfinishedStrokeColor());
bundle.putInt(INSTANCE_MAX, getMax());
bundle.putInt(INSTANCE_PROGRESS, getProgress());
bundle.putString(INSTANCE_SUFFIX, getSuffixText());
bundle.putString(INSTANCE_PREFIX, getPrefixText());
bundle.putFloat(INSTANCE_FINISHED_STROKE_WIDTH, getFinishedStrokeWidth());
bundle.putFloat(INSTANCE_UNFINISHED_STROKE_WIDTH, getUnfinishedStrokeWidth());
bundle.putInt(INSTANCE_BACKGROUND_COLOR, getInnerBackgroundColor());
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if(state instanceof Bundle) {
final Bundle bundle = (Bundle) state;
textColor = bundle.getInt(INSTANCE_TEXT_COLOR);
textSize = bundle.getFloat(INSTANCE_TEXT_SIZE);
finishedStrokeColor = bundle.getInt(INSTANCE_FINISHED_STROKE_COLOR);
unfinishedStrokeColor = bundle.getInt(INSTANCE_UNFINISHED_STROKE_COLOR);
finishedStrokeWidth = bundle.getFloat(INSTANCE_FINISHED_STROKE_WIDTH);
unfinishedStrokeWidth = bundle.getFloat(INSTANCE_UNFINISHED_STROKE_WIDTH);
innerBackgroundColor = bundle.getInt(INSTANCE_BACKGROUND_COLOR);
initPainters();
setMax(bundle.getInt(INSTANCE_MAX));
setProgress(bundle.getInt(INSTANCE_PROGRESS));
prefixText = bundle.getString(INSTANCE_PREFIX);
suffixText = bundle.getString(INSTANCE_SUFFIX);
super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE));
return;
}
super.onRestoreInstanceState(state);
}
}