package com.tiger.quicknews.wedget;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.support.v4.util.LruCache;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import com.tiger.quicknews.R;
public class ProgressPieView extends View {
public interface OnProgressListener {
public void onProgressChanged(int progress, int max);
public void onProgressCompleted();
}
/**
* Fills the progress radially in a clockwise direction.
*/
public static final int FILL_TYPE_RADIAL = 0;
/**
* Fills the progress expanding from the center of the view.
*/
public static final int FILL_TYPE_CENTER = 1;
private static final int DEFAULT_MAX = 100;
private static final int DEFAULT_PROGRESS = 0;
private static final int DEFAULT_START_ANGLE = -90;
private static final float DEFAULT_STROKE_WIDTH = 3f;
private static final float DEFAULT_TEXT_SIZE = 14f;
private static LruCache<String, Typeface> sTypefaceCache = new LruCache<String, Typeface>(8);
private OnProgressListener mListener;
private DisplayMetrics mDisplayMetrics;
private int mMax = DEFAULT_MAX;
private int mProgress = DEFAULT_PROGRESS;
private int mStartAngle = DEFAULT_START_ANGLE;
private boolean mShowStroke = true;
private float mStrokeWidth = DEFAULT_STROKE_WIDTH;
private boolean mShowText = true;
private float mTextSize = DEFAULT_TEXT_SIZE;
private String mText;
private String mTypeface;
private boolean mShowImage = true;
private Drawable mImage;
private Rect mImageRect;
private Paint mStrokePaint;
private Paint mTextPaint;
private Paint mProgressPaint;
private Paint mBackgroundPaint;
private RectF mInnerRectF;
private int mProgressFillType = FILL_TYPE_RADIAL;
public ProgressPieView(Context context) {
this(context, null);
}
public ProgressPieView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ProgressPieView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
mDisplayMetrics = context.getResources().getDisplayMetrics();
mStrokeWidth = mStrokeWidth * mDisplayMetrics.density;
mTextSize = mTextSize * mDisplayMetrics.scaledDensity;
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProgressPieView);
final Resources res = getResources();
mMax = a.getInteger(R.styleable.ProgressPieView_max1, mMax);
mProgress = a.getInteger(R.styleable.ProgressPieView_progress1, mProgress);
mStartAngle = a.getInt(R.styleable.ProgressPieView_startAngle, mStartAngle);
mStrokeWidth = a.getDimension(R.styleable.ProgressPieView_strokeWidth, mStrokeWidth);
mTypeface = a.getString(R.styleable.ProgressPieView_typeface);
mTextSize = a.getDimension(R.styleable.ProgressPieView_android_textSize, mTextSize);
mText = a.getString(R.styleable.ProgressPieView_android_text);
mShowStroke = a.getBoolean(R.styleable.ProgressPieView_showStroke, mShowStroke);
mShowText = a.getBoolean(R.styleable.ProgressPieView_showText, mShowText);
mImage = a.getDrawable(R.styleable.ProgressPieView_image);
int backgroundColor = res.getColor(R.color.default_background_color);
backgroundColor = a.getColor(R.styleable.ProgressPieView_backgroundColor, backgroundColor);
int progressColor = res.getColor(R.color.default_progress_color);
progressColor = a.getColor(R.styleable.ProgressPieView_progressColor1, progressColor);
int strokeColor = res.getColor(R.color.default_stroke_color);
strokeColor = a.getColor(R.styleable.ProgressPieView_strokeColor, strokeColor);
int textColor = res.getColor(R.color.default_text_color);
textColor = a.getColor(R.styleable.ProgressPieView_android_textColor, textColor);
mProgressFillType = a.getInteger(R.styleable.ProgressPieView_progressFillType,
mProgressFillType);
a.recycle();
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBackgroundPaint.setColor(backgroundColor);
mBackgroundPaint.setStyle(Paint.Style.FILL);
mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mProgressPaint.setColor(progressColor);
mProgressPaint.setStyle(Paint.Style.FILL);
mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mStrokePaint.setColor(strokeColor);
mStrokePaint.setStyle(Paint.Style.STROKE);
mStrokePaint.setStrokeWidth(mStrokeWidth);
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(textColor);
mTextPaint.setTextSize(mTextSize);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mInnerRectF = new RectF();
mImageRect = new Rect();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mInnerRectF.set(0, 0, canvas.getWidth(), canvas.getHeight());
final int halfBorder = (int) (mStrokePaint.getStrokeWidth() / 2f + 0.5f);
mInnerRectF.inset(halfBorder, halfBorder);
canvas.drawArc(mInnerRectF, 0, 360, true, mBackgroundPaint);
switch (mProgressFillType) {
case FILL_TYPE_RADIAL:
float sweepAngle = 360 * mProgress / mMax;
canvas.drawArc(mInnerRectF, mStartAngle, sweepAngle, true, mProgressPaint);
break;
case FILL_TYPE_CENTER:
float centerX = canvas.getWidth() / 2;
float centerY = canvas.getHeight() / 2;
float radius = (canvas.getWidth() / 2) * ((float) mProgress / mMax);
canvas.drawCircle(centerX, centerY, radius + 0.5f - mStrokePaint.getStrokeWidth(),
mProgressPaint);
break;
default:
throw new IllegalArgumentException("Invalid Progress Fill = " + mProgressFillType);
}
if (!TextUtils.isEmpty(mText) && mShowText) {
if (!TextUtils.isEmpty(mTypeface)) {
Typeface typeface = sTypefaceCache.get(mTypeface);
if (null == typeface && null != getResources()) {
AssetManager assets = getResources().getAssets();
if (null != assets) {
typeface = Typeface.createFromAsset(assets, mTypeface);
sTypefaceCache.put(mTypeface, typeface);
}
}
mTextPaint.setTypeface(typeface);
}
int xPos = canvas.getWidth() / 2;
int yPos = (int) ((canvas.getHeight() / 2) - ((mTextPaint.descent() + mTextPaint
.ascent()) / 2));
canvas.drawText(mText, xPos, yPos, mTextPaint);
}
if (null != mImage && mShowImage) {
int drawableSize = mImage.getIntrinsicWidth();
mImageRect.set(0, 0, drawableSize, drawableSize);
mImageRect.offset((getWidth() - drawableSize) / 2, (getHeight() - drawableSize) / 2);
mImage.setBounds(mImageRect);
mImage.draw(canvas);
}
if (mShowStroke) {
canvas.drawOval(mInnerRectF, mStrokePaint);
}
}
/**
* Gets the maximum progress value.
*/
public int getMax() {
return mMax;
}
/**
* Sets the maximum progress value. Defaults to 100.
*/
public void setMax(int max) {
if (max <= 0 || max < mProgress) {
throw new IllegalArgumentException(
String.format("Max (%d) must be > 0 and >= %d", max, mProgress));
}
mMax = max;
invalidate();
}
/**
* Gets the current progress from 0 to max.
*/
public int getProgress() {
return mProgress;
}
/**
* Sets the current progress (must be between 0 and max).
*/
public void setProgress(int progress) {
if (progress > mMax || progress < 0) {
throw new IllegalArgumentException(
String.format("Progress (%d) must be between %d and %d", progress, 0, mMax));
}
mProgress = progress;
if (null != mListener) {
if (mProgress == mMax) {
mListener.onProgressCompleted();
} else {
mListener.onProgressChanged(mProgress, mMax);
}
}
invalidate();
}
/**
* Gets the start angle the {@link #FILL_TYPE_RADIAL} uses.
*/
public int getStartAngle() {
return mStartAngle;
}
/**
* Sets the start angle the {@link #FILL_TYPE_RADIAL} uses.
*
* @param startAngle start angle in degrees
*/
public void setStartAngle(int startAngle) {
mStartAngle = startAngle;
}
/**
* Gets the color used to display the progress of the view.
*/
public int getProgressColor() {
return mProgressPaint.getColor();
}
/**
* Sets the color used to display the progress of the view.
*
* @param color - color of the progress part of the view
*/
public void setProgressColor(int color) {
mProgressPaint.setColor(color);
invalidate();
}
/**
* Gets the color used to display the background of the view.
*/
public int getBackgroundColor() {
return mBackgroundPaint.getColor();
}
/**
* Sets the color used to display the background of the view.
*
* @param color - color of the background part of the view
*/
@Override
public void setBackgroundColor(int color) {
mBackgroundPaint.setColor(color);
invalidate();
}
/**
* Gets the color used to display the text of the view.
*/
public int getTextColor() {
return mTextPaint.getColor();
}
/**
* Sets the color used to display the text of the view.
*
* @param color - color of the text part of the view
*/
public void setTextColor(int color) {
mTextPaint.setColor(color);
invalidate();
}
/**
* Gets the text size in sp.
*/
public float getTextSize() {
return mTextSize;
}
/**
* Sets the text size.
*
* @param sizeSp in sp for the text
*/
public void setTextSize(int sizeSp) {
mTextSize = sizeSp * mDisplayMetrics.scaledDensity;
mTextPaint.setTextSize(mTextSize);
invalidate();
}
/**
* Gets the text of the view.
*/
public String getText() {
return mText;
}
/**
* Sets the text of the view.
*
* @param text to be displayed in the view
*/
public void setText(String text) {
mText = text;
invalidate();
}
/**
* Gets the typeface of the text.
*/
public String getTypeface() {
return mTypeface;
}
/**
* Sets the text typeface. - i.e. fonts/Roboto/Roboto-Regular.ttf
*
* @param typeface that the text is displayed in
*/
public void setTypeface(String typeface) {
mTypeface = typeface;
invalidate();
}
/**
* Gets the show text state.
*/
public boolean isTextShowing() {
return mShowText;
}
/**
* Sets the show text state.
*
* @param showText show or hide text
*/
public void setShowText(boolean showText) {
mShowText = showText;
invalidate();
}
/**
* Get the color used to display the stroke of the view.
*/
public int getStrokeColor() {
return mStrokePaint.getColor();
}
/**
* Sets the color used to display the stroke of the view.
*
* @param color - color of the stroke part of the view
*/
public void setStrokeColor(int color) {
mStrokePaint.setColor(color);
invalidate();
}
/**
* Gets the stroke width in dp.
*/
public float getStrokeWidth() {
return mStrokeWidth;
}
/**
* Set the stroke width.
*
* @param widthDp in dp for the pie border
*/
public void setStrokeWidth(int widthDp) {
mStrokeWidth = widthDp * mDisplayMetrics.density;
mStrokePaint.setStrokeWidth(mStrokeWidth);
invalidate();
}
/**
* Gets the show stroke state.
*/
public boolean isStrokeShowing() {
return mShowStroke;
}
/**
* Sets the show stroke state.
*
* @param showStroke show or hide stroke
*/
public void setShowStroke(boolean showStroke) {
mShowStroke = showStroke;
invalidate();
}
/**
* Gets the drawable of the view.
*/
public Drawable getImageDrawable() {
return mImage;
}
/**
* Sets the drawable of the view.
*
* @param image drawable of the view
*/
public void setImageDrawable(Drawable image) {
mImage = image;
invalidate();
}
/**
* Sets the drawable of the view.
*
* @param resId resource id of the view's drawable
*/
public void setImageResource(int resId) {
if (null != getResources()) {
mImage = getResources().getDrawable(resId);
invalidate();
}
}
/**
* Gets the show image state.
*/
public boolean isImageShowing() {
return mShowImage;
}
/**
* Sets the show image state.
*
* @param showImage show or hide image
*/
public void setShowImage(boolean showImage) {
mShowImage = showImage;
invalidate();
}
/**
* Gets the progress fill type.
*/
public int getProgressFillType() {
return mProgressFillType;
}
/**
* Sets the progress fill type.
*
* @param fillType one of {@link #FILL_TYPE_CENTER},
* {@link #FILL_TYPE_RADIAL}
*/
public void setProgressFillType(int fillType) {
mProgressFillType = fillType;
}
/**
* Sets the progress listner.
*
* @param listener progress listener
* @see com.filippudak.ProgressPieView.ProgressPieView.OnProgressListener
*/
public void setOnProgressListener(OnProgressListener listener) {
mListener = listener;
}
}