How to make custom dotted progress bar in android?

后端 未结 3 1008
误落风尘
误落风尘 2020-12-09 23:15

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 design

相关标签:
3条回答
  • 2020-12-09 23:27

    Change onDraw() method to:

    @Override
     protected void onDraw(Canvas canvas){
    super.onDraw(canvas); 
    if(isShown){
        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);
    }
    }
    
    0 讨论(0)
  • 2020-12-09 23:39

    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:

    0 讨论(0)
  • 2020-12-09 23:49

    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();
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题