自定义View 圆形进度条

目录

自定义View 圆形进度条_第1张图片
自定义View 圆形进度条.png

效果

按照惯例,放上效果图


自定义View 圆形进度条_第2张图片
自定义View 圆形进度条.gif

前言

上一篇 文章把断点续传的功能分享了一下,有兴趣的朋友可以看一看。接下来就给大家分享一下自定义View 圆形加载条。

正文

自定义View CirclePercentView
public class CirclePercentView extends View {

    //圆的半径
    private float mRadius;

    //色带的宽度
    private float mStripeWidth;
    //总体大小
    private int mHeight;
    private int mWidth;

    //动画位置百分比进度
    private int mCurPercent;

    //实际百分比进度
    private int mPercent;
    //圆心坐标
    private float x;
    private float y;

    //要画的弧度
    private int mEndAngle;

    //小圆的颜色
    private int mSmallColor;
    //大圆颜色
    private int mBigColor;

    //中心百分比文字大小
    private float mCenterTextSize;

    public CirclePercentView(Context context) {
        this(context, null);
    }

    public CirclePercentView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CirclePercentView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CirclePercentView, defStyleAttr, 0);
        mStripeWidth = a.getDimension(R.styleable.CirclePercentView_stripeWidth, PxUtils.dpToPx(30, context));
        mCurPercent = a.getInteger(R.styleable.CirclePercentView_percent, 0);
        mSmallColor = a.getColor(R.styleable.CirclePercentView_smallColor, 0xffafb4db);
        mBigColor = a.getColor(R.styleable.CirclePercentView_bigColor, 0xff6950a1);
        mCenterTextSize = a.getDimensionPixelSize(R.styleable.CirclePercentView_centerTextSize, PxUtils.spToPx(20, context));
        mRadius = a.getDimensionPixelSize(R.styleable.CirclePercentView_radius, PxUtils.dpToPx(100, context));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //获取测量模式
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        //获取测量大小
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) {
            mRadius = widthSize / 2;
            x = widthSize / 2;
            y = heightSize / 2;
            mWidth = widthSize;
            mHeight = heightSize;
        }

        if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
            mWidth = (int) (mRadius * 2);
            mHeight = (int) (mRadius * 2);
            x = mRadius;
            y = mRadius;

        }

        setMeasuredDimension(mWidth, mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        mEndAngle = (int) (mCurPercent * 3.6);//mCurPercent=0~100.则mEndAngle=0~360.
        //绘制大圆
        Paint bigCirclePaint = new Paint();
        bigCirclePaint.setAntiAlias(true);//抗锯齿,同:别名alias.
        bigCirclePaint.setColor(mBigColor);

        canvas.drawCircle(x, y, mRadius, bigCirclePaint);

        //饼状图,
        Paint sectorPaint = new Paint();
        sectorPaint.setColor(mSmallColor);
        sectorPaint.setAntiAlias(true);

        //精度不一样。Rect是使用int类型作为数值,RectF是使用float类型作为数值。
        RectF rect = new RectF(0, 0, mWidth, mHeight);

//        圆弧arc,即扇形.
        canvas.drawArc(rect, 0, mEndAngle, true, sectorPaint);

//        //绘制小圆,颜色 同 大圆.
//        Paint smallCirclePaint = new Paint();
//        smallCirclePaint.setAntiAlias(true);
//        smallCirclePaint.setColor(mBigColor);
//        canvas.drawCircle(x, y, mRadius - mStripeWidth, smallCirclePaint);

        //绘制文本
        Paint textPaint = new Paint();
        String text = mCurPercent + "%";
        textPaint.setTextSize(mCenterTextSize);
        float textLength = textPaint.measureText(text);
        textPaint.setColor(Color.WHITE);
        canvas.drawText(text, x - textLength / 2, y, textPaint);
    }

    //外部设置百分比数
    public void setPercent(int percent) {
        if (percent > 100) {
            throw new IllegalArgumentException("percent must less than 100!");
        }

        setCurPercent(percent);
    }

    //内部设置百分比 用于动画效果
    private void setCurPercent(int percent) {
        mPercent = percent;

        new Thread(new Runnable() {
            @Override
            public void run() {
                int sleepTime = 1;
                for (int i = 0; i <= mPercent; i++) {
                    if (i % 20 == 0) {
                        sleepTime += 2;
                    }

                    try {
                        Thread.sleep(sleepTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    mCurPercent = i;
                    CirclePercentView.this.postInvalidate();
                }
            }

        }).start();

    }
}
  1. 首先自定义View ,肯定是要继承View类的

  2. CirclePercentView()类中实现了三个构造方法,前两个方法调用第三个方法,我们在第三个方法中初始化自定义的变量,也就是相应的颜色,半径,宽度等等,

  3. onMeasure()方法,继承自View,在方法中获得了视图的宽度和高度,根据高度和宽度,定义了相应的自定义高度和宽度,以及圆的坐标位置。

  4. onDraw()方法,依旧重写于VIew 类中,这个方法就是绘制视图,比较麻烦;

    1. 第一步设置了要画的弧度
    2. 一共3个Plint 和一个CanvasbigCirclePaint 绘制大圆,设置了抗锯齿和颜色,sectorPaint饼状图也就是效果中的扇形,设置了颜色和抗锯齿,textPaint文本,中间的数字,cancas就是画布,plint就相当于画笔,我们把画笔画在画布上就成功的现实了上面的效果
  5. 最后两个方法:外部百分比和内部的百分比,内部的百分比有一个动画效果;外部就是给外部留下了方法可以调用;

PxUtils
/**
 * 用于px和  dp,sp的转换工具
 */
public class PxUtils {

    public static int dpToPx(int dp, Context context) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
    }

    public static int spToPx(int sp,Context context) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics());
    }
}

此方法就是dp和sp转为px的方法

主方法 MainActivity
public class MainActivity extends AppCompatActivity {
    
    private Button mButton;
    private CirclePercentView mCirclePercentView;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mCirclePercentView = (CirclePercentView) findViewById(R.id.circleView);
        mButton = (Button) findViewById(R.id.button);
        
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int n = (int)(1*100);
                mCirclePercentView.setPercent(n);
            }
        });
    }
}
  1. 定义了一个自定义View,一个Button
  2. 通过点击事件设置进度

activity_main 视图




    

总结

其实自定义View就是很简单的东西 ,我们可以自己动手操作一下就可以了,主要就是画笔和画布之间,然后动态效果就是通过线程更新UI;就每次都重新绘画一下视图。

感谢

该项目是在网上浏览的时候看见的,给大家奉上Github的地址

你可能感兴趣的:(自定义View 圆形进度条)