如何在android中自定义虚线进度条?

时间:2016-06-10 07:00:46

标签: android

自定义进度条,点应用动画并赋予遍历视觉效果。在此发布此代码是因为它可以帮助您理解和实现新设计,同时将此作为参考。希望这可以帮助你。

3 个答案:

答案 0 :(得分:21)

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>
&#13;
&#13;
&#13;

Horizo​​ntalDottedProgress.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

答案 1 :(得分:1)

我使用了Horizo​​ntalDottedProgress类 - 这是一个真正的解决方案,但它有时会绘制非常小的点。此小部件也不会对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();
        }
    }
}

答案 2 :(得分: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);
}
}