Skip to content

Instantly share code, notes, and snippets.

@rafakob
Created April 17, 2016 14:16
Show Gist options
  • Save rafakob/b2eceb43c6286a9381a3c5cb18eaacde to your computer and use it in GitHub Desktop.
Save rafakob/b2eceb43c6286a9381a3c5cb18eaacde to your computer and use it in GitHub Desktop.
<declare-styleable name="CircleProgressBar">
<attr name="cpb_min" format="integer"/>
<attr name="cpb_max" format="integer"/>
<attr name="cpb_progress" format="integer"/>
<attr name="cpb_startAngle" format="integer"/>
<attr name="cpb_color" format="color"/>
<attr name="cpb_colorBack" format="color"/>
<attr name="cpb_backAlpha" format="float"/>
<attr name="cpb_stroke" format="dimension"/>
<attr name="cpb_strokeFinal" format="dimension"/>
<attr name="cpb_animDuration" format="integer"/>
</declare-styleable>
GIF: http://i.giphy.com/26AHH8u6ailoD3hpm.gif
public class CircleProgressBar extends View {
/* Attributes */
private int mMin = 0;
private int mMax = 100;
private float mProgress = 0;
private float mStroke = 5;
private float mStrokeFinal;
private int mColor = Color.DKGRAY;
private int mColorBack;
private float mBackAlpha = 0.3f;
private int mStartAngle = -90;
private int mAnimDuration = 1000;
/* Internal */
private Paint mForegroundPaint;
private Paint mBackgroundPaint;
private RectF mRectF;
private boolean mIsStrokeExpanded;
public CircleProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
mRectF = new RectF();
mIsStrokeExpanded = false;
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CircleProgressBar, 0, 0);
try {
mMin = typedArray.getInt(R.styleable.CircleProgressBar_cpb_min, mMin);
mMax = typedArray.getInt(R.styleable.CircleProgressBar_cpb_max, mMax);
mProgress = typedArray.getFloat(R.styleable.CircleProgressBar_cpb_progress, mProgress);
mStroke = typedArray.getDimension(R.styleable.CircleProgressBar_cpb_stroke, mStroke);
mStrokeFinal = typedArray.getDimension(R.styleable.CircleProgressBar_cpb_strokeFinal, mStroke);
mColor = typedArray.getInt(R.styleable.CircleProgressBar_cpb_color, mColor);
mColorBack = typedArray.getInt(R.styleable.CircleProgressBar_cpb_colorBack, mColor);
mBackAlpha = typedArray.getFloat(R.styleable.CircleProgressBar_cpb_backAlpha, mBackAlpha);
mStartAngle = typedArray.getInt(R.styleable.CircleProgressBar_cpb_startAngle, mStartAngle);
mAnimDuration = typedArray.getInt(R.styleable.CircleProgressBar_cpb_animDuration, mAnimDuration);
} finally {
typedArray.recycle();
}
mColorBack = ColorUtils.adjustAlpha(mColorBack, mBackAlpha);
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBackgroundPaint.setColor(mColorBack);
mBackgroundPaint.setStyle(Paint.Style.STROKE);
mBackgroundPaint.setStrokeWidth(mStroke);
mForegroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mForegroundPaint.setColor(mColor);
mForegroundPaint.setStyle(Paint.Style.STROKE);
mForegroundPaint.setStrokeWidth(mStroke);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
final int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int min = Math.min(width, height);
setMeasuredDimension(min, min);
mRectF.set(0 + mStrokeFinal / 2, 0 + mStrokeFinal / 2, min - mStrokeFinal / 2, min - mStrokeFinal / 2);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float angle = 360 * mProgress / mMax;
canvas.drawOval(mRectF, mBackgroundPaint);
canvas.drawArc(mRectF, mStartAngle, angle, false, mForegroundPaint);
}
public void setStroke(float stroke) {
mStroke = stroke;
mForegroundPaint.setStrokeWidth(stroke);
invalidate();
}
public void setProgress(float progress) {
mProgress = progress;
invalidate();
}
public void setAnimDuration(int animDuration) {
mAnimDuration = animDuration;
}
public Animator setProgressWithAnimation(float progress) {
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator progressAnimator = ObjectAnimator.ofFloat(this, "progress", mProgress, progress);
progressAnimator.setDuration(mAnimDuration);
progressAnimator.setInterpolator(new AccelerateInterpolator());
if (mProgress == 0) {
mIsStrokeExpanded = false;
}
if (mStroke == mStrokeFinal || mIsStrokeExpanded) {
progressAnimator.start();
return progressAnimator;
}
ValueAnimator strokeAnimator = ValueAnimator.ofFloat(mStroke, mStrokeFinal);
strokeAnimator.setDuration(mAnimDuration);
strokeAnimator.setInterpolator(new CircInInterpolator());
strokeAnimator.addUpdateListener(valueAnimator1 -> {
mForegroundPaint.setStrokeWidth((float) valueAnimator1.getAnimatedValue());
invalidate();
});
animatorSet.playTogether(progressAnimator, strokeAnimator);
animatorSet.start();
mIsStrokeExpanded = true;
return animatorSet;
}
public static class CircInInterpolator implements TimeInterpolator {
@Override
public float getInterpolation(float elapsedTimeRate) {
return (float) -(Math.sqrt(1f - elapsedTimeRate * elapsedTimeRate) - 1);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment