Custom progress bar with dots applied animation and given the traversing visual effect. Posting this code here because it can help you to understand and implement new designs too keeping this as reference. Hope this helps you people.
MainActivity.java :
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rect"
android:gravity="center"
>
<com.example.horizontal.canvaslearn.HorizontalDottedProgress
android:layout_width="wrap_content"
android:layout_height="wrap_content"
></com.example.horizontal.canvaslearn.HorizontalDottedProgress>
</LinearLayout>
HorizontalDottedProgress.java : This is a custom class to create dots with animation applied.
public class HorizontalDottedProgress extends View{
//actual dot radius
private int mDotRadius = 5;
//Bounced Dot Radius
private int mBounceDotRadius = 8;
//to get identified in which position dot has to bounce
private int mDotPosition;
//specify how many dots you need in a progressbar
private int mDotAmount = 10;
public HorizontalDottedProgress(Context context) {
super(context);
}
public HorizontalDottedProgress(Context context, AttributeSet attrs) {
super(context, attrs);
}
public HorizontalDottedProgress(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
//Method to draw your customized dot on the canvas
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
//set the color for the dot that you want to draw
paint.setColor(Color.parseColor("#fd583f"));
//function to create dot
createDot(canvas,paint);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
//Animation called when attaching to the window, i.e to your screen
startAnimation();
}
private void createDot(Canvas canvas, Paint paint) {
//here i have setted progress bar with 10 dots , so repeat and wnen i = mDotPosition then increase the radius of dot i.e mBounceDotRadius
for(int i = 0; i < mDotAmount; i++ ){
if(i == mDotPosition){
canvas.drawCircle(10+(i*20), mBounceDotRadius, mBounceDotRadius, paint);
}else {
canvas.drawCircle(10+(i*20), mBounceDotRadius, mDotRadius, paint);
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width;
int height;
//calculate the view width
int calculatedWidth = (20*9);
width = calculatedWidth;
height = (mBounceDotRadius*2);
//MUST CALL THIS
setMeasuredDimension(width, height);
}
private void startAnimation() {
BounceAnimation bounceAnimation = new BounceAnimation();
bounceAnimation.setDuration(100);
bounceAnimation.setRepeatCount(Animation.INFINITE);
bounceAnimation.setInterpolator(new LinearInterpolator());
bounceAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
mDotPosition++;
//when mDotPosition == mDotAmount , then start again applying animation from 0th positon , i.e mDotPosition = 0;
if (mDotPosition == mDotAmount) {
mDotPosition = 0;
}
Log.d("INFOMETHOD","----On Animation Repeat----");
}
});
startAnimation(bounceAnimation);
}
private class BounceAnimation extends Animation {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
//call invalidate to redraw your view againg.
invalidate();
}
}
}
snap shot:
I have used the class HorizontalDottedProgress - this is a real solution, but it sometimes draws very small dots. Also this widget doesn't react on setVisibility(Visibility.GONE) and can't be hidden after showing.
That's why I slightly modified (and renamed for myself) this class. Dot sizes and distances are calculated using screen density now. Function onDraw() checks isShown() before drawing.
Then, I've added a possibility to specify some properties (such as color, count and timeout) in layout. In my project I use them in the following manner:
<my.domain.tools.ToolDotProgress
android:id="@+id/dots_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:color="@color/colorAccent"
app:count="5"
app:timeout="300" />
To declare these properties I've added to file res/values/attrs.xml the following code:
<declare-styleable name="ToolDotProgress">
<attr name="color" format="color" />
<attr name="count" format="integer" />
<attr name="timeout" format="integer" />
</declare-styleable>
For more information read the manual: https://developer.android.com/training/custom-views/create-view.html
Here is my variant of this class:
public class ToolDotProgress extends View {
// distance between neighbour dot centres
private int mDotStep = 20;
// actual dot radius
private int mDotRadius = 5;
// Bounced Dot Radius
private int mBigDotRadius = 8;
// to get identified in which position dot has to bounce
private int mDotPosition;
// specify how many dots you need in a progressbar
private static final int MIN_COUNT = 1;
private static final int DEF_COUNT = 10;
private static final int MAX_COUNT = 100;
private int mDotCount = DEF_COUNT;
private static final int MIN_TIMEOUT = 100;
private static final int DEF_TIMEOUT = 500;
private static final int MAX_TIMEOUT = 3000;
private int mTimeout = DEF_TIMEOUT;
private int mDotColor = Color.parseColor("#fd583f");
public ToolDotProgress(Context context) {
super(context);
initDotSize();
}
public ToolDotProgress(Context context, AttributeSet attrs) {
super(context, attrs);
initDotSize();
applyAttrs(context, attrs);
}
public ToolDotProgress(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initDotSize();
applyAttrs(context, attrs);
}
private void initDotSize() {
final float scale = getResources().getDisplayMetrics().density;
mDotStep = (int)(mDotStep * scale);
mDotRadius = (int)(mDotRadius * scale);
mBigDotRadius = (int)(mBigDotRadius * scale);
}
private void applyAttrs(Context context, AttributeSet attrs) {
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs, R.styleable.ToolDotProgress, 0, 0);
try {
mDotColor = a.getColor(R.styleable.ToolDotProgress_color, mDotColor);
mDotCount = a.getInteger(R.styleable.ToolDotProgress_count, mDotCount);
mDotCount = Math.min(Math.max(mDotCount, MIN_COUNT), MAX_COUNT);
mTimeout = a.getInteger(R.styleable.ToolDotProgress_timeout, mTimeout);
mTimeout = Math.min(Math.max(mTimeout, MIN_TIMEOUT), MAX_TIMEOUT);
} finally {
a.recycle();
}
}
//Method to draw your customized dot on the canvas
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isShown()) {
Paint paint = new Paint();
paint.setColor(mDotColor);
createDots(canvas, paint);
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
startAnimation();
}
private void createDots(Canvas canvas, Paint paint) {
for (int i = 0; i < mDotCount; i++ ) {
int radius = (i == mDotPosition) ? mBigDotRadius : mDotRadius;
canvas.drawCircle(mDotStep / 2 + (i * mDotStep), mBigDotRadius, radius, paint);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// MUST CALL THIS
setMeasuredDimension(mDotStep * mDotCount, mBigDotRadius * 2);
}
private void startAnimation() {
BounceAnimation bounceAnimation = new BounceAnimation();
bounceAnimation.setDuration(mTimeout);
bounceAnimation.setRepeatCount(Animation.INFINITE);
bounceAnimation.setInterpolator(new LinearInterpolator());
bounceAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
if (++mDotPosition >= mDotCount) {
mDotPosition = 0;
}
}
});
startAnimation(bounceAnimation);
}
private class BounceAnimation extends Animation {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
// call invalidate to redraw your view again
invalidate();
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With