天天看点

Android开发自定义View之进度条(个人记录)

效果图是一切代码的结果

Android开发自定义View之进度条(个人记录)

标题

代码分析:

public XTestStepView(Context context) {
    super(context);
    init();
}

public XTestStepView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    init();
}

public XTestStepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.XQQStepView);
    mOuterColor = typedArray.getColor(R.styleable.XQQStepView_outerColor, mOuterColor);
    mInnerColor = typedArray.getColor(R.styleable.XQQStepView_innerColor, mInnerColor);
    mBorderWidth = (int) typedArray.getDimension(R.styleable.XQQStepView_borderWidth, mBorderWidth);
    mStepTextSize = typedArray.getDimensionPixelOffset(R.styleable.XQQStepView_stepTextSize, mStepTextSize);
    mStepTextColor = typedArray.getColor(R.styleable.XQQStepView_stepTextColor, mStepTextColor);
    typedArray.recycle();

    init();
}
           

自定义控件必要继承的几个方法就不多说了,其中第三个方法里面是设置相关属性;

定义画笔工具

private void init() {
    //内弧
    mOuterPaint = new Paint();
    mOuterPaint.setAntiAlias(true);
    mOuterPaint.setStrokeWidth(mBorderWidth);
    mOuterPaint.setColor(mOuterColor);
    mOuterPaint.setStrokeCap(Paint.Cap.ROUND);//设置下方为圆形
    mOuterPaint.setStyle(Paint.Style.STROKE);//设置内部为空心
    //外弧
    mInnerPaint = new Paint();
    mInnerPaint.setAntiAlias(true);
    mInnerPaint.setStrokeWidth(mBorderWidth);
    mInnerPaint.setColor(mInnerColor);
    mInnerPaint.setStrokeCap(Paint.Cap.ROUND);//设置下方为圆形
    mInnerPaint.setStyle(Paint.Style.STROKE);//设置内部为空心

    //文字
    mTextPaint = new Paint();
    mTextPaint.setAntiAlias(true);
    mTextPaint.setTextSize(mStepTextSize);
    mTextPaint.setStrokeWidth(2);
    mTextPaint.setColor(mStepTextColor);
}
           

不明白属性的百度,最基础的画笔属性,没法再做解释

接下来获取宽高:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);

    setMeasuredDimension(width > height ? height : width, width > height ? height : width);
}
           

画布,解释在代码里面:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    //画外圆
    int center = getWidth() / 2;
    int radius = getWidth() / 2 - mBorderWidth / 2;
    //mBorderWidth/2,mBorderWidth/2,getWidth()-mBorderWidth/2,getWidth()-mBorderWidth/2
    @SuppressLint("DrawAllocation") RectF recf = new RectF(center - radius,
            center - radius,
            center + radius,
            center + radius);
    canvas.drawArc(recf, 90, 360, false, mOuterPaint);
    //2.绘制内圆弧
    float sweepAngle = (float) mCurrentStep / mStepMax;
    canvas.drawArc(recf, 90, sweepAngle * 360, false, mInnerPaint);

    //3.绘制文字
    String stepText = mCurrentStep + "";
    Rect rect = new Rect();
    mTextPaint.getTextBounds(stepText,0,stepText.length(),rect);
    int dx = getWidth() / 2 - rect.width() / 2;
    //第一种方式获取高度
    //int dy = getWidth() / 2 + rect.width()/2;
    //第二种表达方式获取高度
    Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
    //获取中心(fontMetrics.bottom - fontMetrics.top) / 2
    int dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
    int baseLine = getHeight() / 2 + dy;
    canvas.drawText(stepText, dx, baseLine, mTextPaint);
    Log.e("stepText:",stepText +"..."+sweepAngle);
}
           

最后是完整的代码:

public class XTestStepView extends View {

    //    <!--内部圆环颜色,外部圆环颜色,圆环宽度,文字颜色,文字大小-->
    private int mOuterColor = Color.RED;
    private int mInnerColor = Color.BLUE;
    private int mBorderWidth = 20;
    private int mStepTextSize = 50;
    private int mStepTextColor = Color.RED;
    private Paint mOuterPaint, mInnerPaint, mTextPaint;
    private int mStepMax;//总的步数
    private int mCurrentStep;//当前步数

    public XTestStepView(Context context) {
        super(context);
        init();
    }

    public XTestStepView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public XTestStepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.XQQStepView);
        mOuterColor = typedArray.getColor(R.styleable.XQQStepView_outerColor, mOuterColor);
        mInnerColor = typedArray.getColor(R.styleable.XQQStepView_innerColor, mInnerColor);
        mBorderWidth = (int) typedArray.getDimension(R.styleable.XQQStepView_borderWidth, mBorderWidth);
        mStepTextSize = typedArray.getDimensionPixelOffset(R.styleable.XQQStepView_stepTextSize, mStepTextSize);
        mStepTextColor = typedArray.getColor(R.styleable.XQQStepView_stepTextColor, mStepTextColor);
        typedArray.recycle();

        init();
    }

    public XTestStepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    private void init() {
        //内弧
        mOuterPaint = new Paint();
        mOuterPaint.setAntiAlias(true);
        mOuterPaint.setStrokeWidth(mBorderWidth);
        mOuterPaint.setColor(mOuterColor);
        mOuterPaint.setStrokeCap(Paint.Cap.ROUND);//设置下方为圆形
        mOuterPaint.setStyle(Paint.Style.STROKE);//设置内部为空心
        //外弧
        mInnerPaint = new Paint();
        mInnerPaint.setAntiAlias(true);
        mInnerPaint.setStrokeWidth(mBorderWidth);
        mInnerPaint.setColor(mInnerColor);
        mInnerPaint.setStrokeCap(Paint.Cap.ROUND);//设置下方为圆形
        mInnerPaint.setStyle(Paint.Style.STROKE);//设置内部为空心

        //文字
        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(mStepTextSize);
        mTextPaint.setStrokeWidth(2);
        mTextPaint.setColor(mStepTextColor);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        setMeasuredDimension(width > height ? height : width, width > height ? height : width);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //画外圆
        int center = getWidth() / 2;
        int radius = getWidth() / 2 - mBorderWidth / 2;
        //mBorderWidth/2,mBorderWidth/2,getWidth()-mBorderWidth/2,getWidth()-mBorderWidth/2
        @SuppressLint("DrawAllocation") RectF recf = new RectF(center - radius,
                center - radius,
                center + radius,
                center + radius);
        canvas.drawArc(recf, 90, 360, false, mOuterPaint);
        //2.绘制内圆弧
        float sweepAngle = (float) mCurrentStep / mStepMax;
        canvas.drawArc(recf, 90, sweepAngle * 360, false, mInnerPaint);

        //3.绘制文字
        String stepText = mCurrentStep + "";
        Rect rect = new Rect();
        mTextPaint.getTextBounds(stepText,0,stepText.length(),rect);
        int dx = getWidth() / 2 - rect.width() / 2;
        //第一种方式获取高度
        //int dy = getWidth() / 2 + rect.width()/2;
        //第二种表达方式获取高度
        Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
        //获取中心(fontMetrics.bottom - fontMetrics.top) / 2
        int dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
        int baseLine = getHeight() / 2 + dy;
        canvas.drawText(stepText, dx, baseLine, mTextPaint);
        Log.e("stepText:",stepText +"..."+sweepAngle);
    }

    //其他,写几个方法让他动起来
    public void setStepMax(int mStepMax) {
        this.mStepMax = mStepMax;
    }

    public void setCurrentStep(int mCurrentStep) {
        this.mCurrentStep = mCurrentStep;
        //不断绘制 onDraw()
        invalidate();
    }
}
           

接下来,我会将中间的文字放在进度条中,跟随实时