Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make custom dotted progress bar in android?

Tags:

android

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.

like image 879
Naveen Shriyan Avatar asked Jun 10 '16 07:06

Naveen Shriyan


2 Answers

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:

enter image description here

like image 111
Naveen Shriyan Avatar answered Sep 20 '22 15:09

Naveen Shriyan


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();
        }
    }
}
like image 30
Alexander Gavriliuk Avatar answered Sep 21 '22 15:09

Alexander Gavriliuk