如何在安卓中制作自定义的点状进度条?

10

定制带有点动画效果和遍历视觉效果的进度条。我在这里发布此代码,因为它可以帮助您理解并使用新设计作为参考实现。希望这能对您有所帮助。

3个回答

53

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 : 这是一个自定义类,用于创建带有动画的点。

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();
    }
}
}

快照:

enter image description here


因为动画仍在运行,所以首先要清除动画,像这样:horizontalDotsProgressBar.clearAnimation(); horizontalDotsProgressBar.setVisibility(View.GONE); - Shashank Verma

6
我使用了HorizontalDottedProgress类 - 这是一个真正的解决方案,但有时它会绘制非常小的点。此外,该部件不会对setVisibility(Visibility.GONE)做出反应,显示后无法隐藏。
因此,我稍微修改了这个类(并为自己重新命名)。现在,点的大小和距离是使用屏幕密度计算的。在绘制之前,onDraw()函数检查isShown()。
然后,我添加了在布局中指定某些属性(例如颜色、计数和超时)的可能性。在我的项目中,我以以下方式使用它们:
<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" />

为了声明这些属性,我已经将以下代码添加到文件res/values/attrs.xml中:
<declare-styleable name="ToolDotProgress">
    <attr name="color" format="color" />
    <attr name="count" format="integer" />
    <attr name="timeout" format="integer" />
</declare-styleable>

有关更多信息,请阅读手册:https://developer.android.com/training/custom-views/create-view.html

这是我对这个类的变体:

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
将onDraw()方法更改为:
@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);
}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接