天天看點

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

接下來,我會将中間的文字放在進度條中,跟随實時