Created
March 9, 2015 12:30
-
-
Save avatsav/1bedd061dc7be76ceb07 to your computer and use it in GitHub Desktop.
BellyProgressbar
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class BellyProgressBar extends ProgressBar { | |
private int mColor; | |
private float mStrokeWidth; | |
private float mRotationSpeed = 1f; | |
public BellyProgressBar(Context context) { | |
super(context); | |
init(context); | |
} | |
public BellyProgressBar(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
init(context); | |
} | |
public BellyProgressBar(Context context, AttributeSet attrs, int defStyle) { | |
super(context, attrs, defStyle); | |
init(context); | |
} | |
private void init(Context context) { | |
mColor = context.getResources().getColor(R.color.payment_progress_bar_default_color); | |
mStrokeWidth = context.getResources().getDimension(R.dimen.bpb_default_stroke_width); | |
setLayerType(View.LAYER_TYPE_SOFTWARE, null); | |
setIndeterminateDrawable(new BellyProgressDrawable(mColor, mStrokeWidth, mRotationSpeed)); | |
} | |
public void setBellyColor(int color) { | |
mColor = color; | |
checkIndeterminateDrawable().setBellyColor(mColor); | |
} | |
public void setStrokeWidth(float strokeWidth) { | |
mStrokeWidth = strokeWidth; | |
checkIndeterminateDrawable().setStrokeWidth(mStrokeWidth); | |
} | |
public void setRotationSpeed(float speed) { | |
mRotationSpeed = speed; | |
checkIndeterminateDrawable().setRotationSpeed(mRotationSpeed); | |
} | |
public void progressiveStop() { | |
checkIndeterminateDrawable().stop(); | |
} | |
private BellyProgressDrawable checkIndeterminateDrawable() { | |
Drawable ret = getIndeterminateDrawable(); | |
if (ret == null || !(ret instanceof BellyProgressDrawable)) | |
throw new RuntimeException("The drawable is not a BellyProgressDrawable"); | |
return (BellyProgressDrawable) ret; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class BellyProgressDrawable extends Drawable implements Animatable { | |
private static final Interpolator ROTATION_INTERPOLATOR = null; //new CubicBezierInterpolator(0.4, 0, 0.2, 1); //Ease-in-out | |
private static final int ROTATION_ANIMATOR_DURATION = 1500; //ms | |
private Rect fBounds = new Rect(); | |
private Paint mPaint; | |
private ValueAnimator mRotationAnimator; | |
private float mCurrentRotationAngle; | |
private float mOuterRadius; | |
private float mInnerRadius; | |
private float[] mOuterCircleCenter; | |
private float[] mInnerCircleCenter; | |
private boolean mRunning; | |
//params | |
private int mColor; | |
private float mStrokeWidth; | |
private float mRotationSpeed; | |
public BellyProgressDrawable(int color, float strokeWidth, float rotationSpeed) { | |
mColor = color; | |
mStrokeWidth = strokeWidth; | |
mRotationSpeed = rotationSpeed; | |
mPaint = new Paint(); | |
mPaint.setAntiAlias(true); | |
mPaint.setStyle(Paint.Style.FILL); | |
mPaint.setColor(mColor); | |
setupAnimations(); | |
} | |
@Override | |
public void draw(Canvas canvas) { | |
canvas.save(); | |
canvas.rotate(mCurrentRotationAngle, fBounds.centerX(), fBounds.centerY()); | |
mPaint.setXfermode(null); | |
canvas.drawCircle(mOuterCircleCenter[0], mOuterCircleCenter[1], mOuterRadius, mPaint); //DST | |
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); | |
canvas.drawCircle(mInnerCircleCenter[0], mInnerCircleCenter[1], mInnerRadius, mPaint); //SRC | |
canvas.restore(); | |
} | |
@Override | |
protected void onBoundsChange(Rect bounds) { | |
super.onBoundsChange(bounds); | |
// Called only once! Much performance! Such smooth! So awesome! | |
calculateCircleMeasurements(); | |
} | |
private void calculateCircleMeasurements() { | |
fBounds = getBounds(); | |
float size = Math.min(fBounds.height(), fBounds.width()); | |
mOuterRadius = (size / 2) - mStrokeWidth / 2; | |
mInnerRadius = (size / 2) - (3 * mStrokeWidth) / 2; | |
// Outer circle center; | |
mOuterCircleCenter = new float[2]; | |
mOuterCircleCenter[0] = fBounds.centerX(); | |
mOuterCircleCenter[1] = fBounds.centerY() - mStrokeWidth / 2; | |
// Inner mask circle center; | |
mInnerCircleCenter = new float[2]; | |
mInnerCircleCenter[0] = fBounds.centerX(); | |
mInnerCircleCenter[1] = fBounds.centerY(); | |
} | |
private void setupAnimations() { | |
mRotationAnimator = ValueAnimator.ofFloat(0f, 360f); | |
//mRotationAnimator.setInterpolator(ROTATION_INTERPOLATOR); | |
mRotationAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { | |
@Override | |
public void onAnimationUpdate(ValueAnimator animation) { | |
float angle = getAnimatedFraction(animation) * 360f; | |
setCurrentRotationAngle(angle); | |
} | |
}); | |
mRotationAnimator.setDuration((long) (ROTATION_ANIMATOR_DURATION / mRotationSpeed)); | |
mRotationAnimator.setRepeatCount(ValueAnimator.INFINITE); | |
mRotationAnimator.setRepeatMode(ValueAnimator.RESTART); | |
} | |
private float getAnimatedFraction(ValueAnimator animation) { | |
float fraction = animation.getDuration() > 0 ? ((float) animation.getCurrentPlayTime()) / animation.getDuration() : 1f; | |
fraction %= 1f; | |
fraction = min(fraction, 1f); | |
fraction = animation.getInterpolator().getInterpolation(fraction); | |
return fraction; | |
} | |
private void setCurrentRotationAngle(float currentRotationAngle) { | |
mCurrentRotationAngle = currentRotationAngle; | |
invalidateSelf(); | |
} | |
@Override | |
public void start() { | |
if (isRunning()) | |
return; | |
mRunning = true; | |
mRotationAnimator.start(); | |
invalidateSelf(); | |
} | |
@Override | |
public void stop() { | |
if (!isRunning()) | |
return; | |
mRunning = false; | |
mRotationAnimator.cancel(); | |
invalidateSelf(); | |
} | |
public void setBellyColor(int newColor) { | |
mColor = newColor; | |
mPaint.setColor(mColor); | |
} | |
public void setStrokeWidth(float strokeWidth) { | |
mStrokeWidth = strokeWidth; | |
calculateCircleMeasurements(); | |
} | |
public void setRotationSpeed(float speed) { | |
mRotationSpeed = speed; | |
mRotationAnimator.setDuration((long) (ROTATION_ANIMATOR_DURATION / mRotationSpeed)); | |
setupAnimations(); | |
invalidateSelf(); | |
} | |
@Override | |
public boolean isRunning() { | |
return mRunning; | |
} | |
@Override | |
public void setAlpha(int alpha) { | |
mPaint.setAlpha(alpha); | |
} | |
@Override | |
public void setColorFilter(ColorFilter cf) { | |
mPaint.setColorFilter(cf); | |
} | |
@Override | |
public int getOpacity() { | |
return PixelFormat.TRANSPARENT; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment