This custom view shows a clock-like circular countdown, and can be used as a timer or as a ProgressBar
. To use as a timer, create your own handler (or similar) to update the progress automatically.
Based on source code from FreeOTP released under Apache 2.0 license.
Usage
<com.pixplicity.example.ui.CircleProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:max="1000"
android:padding="6dp"
android:progress="750" />
ProgressTextView.java
package com.pixplicity.example.ui;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.widget.ProgressBar;
import com.pixplicity.example.R;
public class CircleProgressBar extends ProgressBar {
private static final int PADDING = 6;
private Paint paintBorder;
private Paint paint;
private RectF rectf;
private Rect rect;
private LinearGradient mGradient;
public CircleProgressBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();
}
public CircleProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public CircleProgressBar(Context context) {
super(context);
setup();
}
private void setup() {
paint = new Paint();
paintBorder = new Paint();
rectf = new RectF();
rect = new Rect();
paint.setColor(ContextCompat.getColor(getContext(), R.color.progress_color));
paint.setAntiAlias(true);
paint.setStyle(Style.FILL_AND_STROKE);
paintBorder.setColor(ContextCompat.getColor(getContext(), R.color.progress_border));
paintBorder.setAntiAlias(true);
paintBorder.setStyle(Style.STROKE);
paintBorder.setStrokeWidth(2);
}
@Override
public synchronized void setProgress(int progress) {
super.setProgress(progress);
if (paint != null) {
int percent = progress * 100 / getMax();
if (percent > 25 || progress == 0) {
paint.setColor(ContextCompat.getColor(getContext(), R.color.progress_color));
paint.setShader(mGradient);
} else {
paint.setARGB(0x99, 0xff, 0xe0 * percent / 25, 0x00);
paint.setShader(null);
}
}
}
@Override
protected synchronized void onDraw(Canvas canvas) {
getDrawingRect(rect);
rect.left += getPaddingLeft();
rect.top += getPaddingTop();
rect.right -= getPaddingRight();
rect.bottom -= getPaddingBottom();
rectf.set(rect);
canvas.drawOval(rectf, paintBorder);
rect.left += PADDING;
rect.top += PADDING;
rect.right -= PADDING;
rect.bottom -= PADDING;
rectf.set(rect);
if (mGradient == null) {
mGradient = new LinearGradient(0, 0, 100, 100,
ContextCompat.getColor(getContext(), R.color.progress_color_light),
ContextCompat.getColor(getContext(), R.color.progress_color),
TileMode.CLAMP);
}
float sweep = getProgress() * 360 / getMax();
float angle = 270 - sweep;
canvas.drawArc(rectf, angle, sweep, true, paint);
}
}