Android繪製圓形進度條

來源:互聯網
上載者:User

標籤:ogre   attribute   res   rri   ted   value   決定   介紹   總結   

一、背景介紹

我們在項目中,經常會見到圓形進度條,看起來很美觀、直觀。剛好最近項目中有這樣的需求,記錄一下,順便回顧下自訂View的知識。

二、實現思路

自訂View,就是在畫布中繪製View,需要重寫onDraw方法。該View可以拆分成以下幾部分:

1)需要畫一個淺綠色的圓

2)需要畫一個白色的圓

3)圓圈中有進度數位顯示

4)圓圈中可以自訂頂部和底部不同文案的提示

三、主要方法介紹

1、drawArc:由可以看出,該圓需要畫出圓弧表示進度,所以選擇drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)方法。

1)參數:

oval-用於確定圓弧形狀與尺寸的橢圓邊界(即橢圓外切矩形)

startAngle-開始角度(以時鐘3點鐘為0°,逆時針為正方向)

sweepAngle-旋轉角度(以時鐘3點鐘為0°,逆時針為正方向)

useCenter-是否包含圓心

paint-畫筆

2)繪製原理

  • 當RectF(float left,float top,float right,float bottom)中right-left等於bottom-top時(長=寬),這時畫出的就是個圓。

    

  • 以矩形中心為圓心,以3點鐘方向為0°,逆時針為正方向,從0°旋轉startAngle度,和橢圓相交得到一條直線和一個焦點。

    

  • 從這條直線開始,正方向旋轉sweepAngle度,得到另一條直線和焦點,這樣就可以得到兩個焦點間的圓弧。

    

2、drawText(String text, float x, float y, Paint paint):文本的繪製方法。

參數:

text-文本

x-該文本的左邊與螢幕左邊的距離

y-該文本baseline在螢幕上的位置

paint-畫筆

需要注意的是,參數y不是表示豎直方向上的位置,而是該文本baseline在螢幕上的位置。

根據官方API說明,Paint的TextAlign屬性決定了text相對於起始座標x的相對位置。預設left,文本從x的右邊開始繪製,如果是center,則x座標在文本的中間。

baseline的介紹參考:http://www.xyczero.com/blog/article/20/

四、畫圓

1)畫一個背景圓

        //1-圓弧的位置:整圓,再繪製進度圓弧        mArcCirclePaint.setColor(mCircleBackgroundColor);        mArcCirclePaint.setStrokeWidth(mStrokeWidth);        //螢幕寬度        int width = getMeasuredWidth();        RectF rectF = new RectF();        rectF.left = (width-mWidth)/2;//左上方X        rectF.top = mWidth*0.1f;//左上方Y        rectF.right = (width-mWidth)/2+mWidth;//右上方X        rectF.bottom = mWidth*0.9f;//右上方Y        if ((rectF.right - rectF.left) > (rectF.bottom- rectF.top)){//正方形矩形,保證畫出的圓不會變成橢圓            float space = (rectF.right - rectF.left) - (rectF.bottom- rectF.top);            rectF.left += space/2;            rectF.right -= space/2;        }        canvas.drawArc(rectF,270,360,false,mArcCirclePaint);//第2個參數:時鐘3點處為0度,逆時針為正方向

2)畫進度圓

使用同一個Paint,改變其顏色,在畫布上繪製一樣大小的圓,只是旋轉角度值不一樣。

 mArcCirclePaint.setColor(mProgressColor); //設定邊角為圓 mArcCirclePaint.setStrokeCap(Paint.Cap.ROUND); mArcCirclePaint.setStrokeWidth(mInnerStrokeWidth); canvas.drawArc(rectF,270,mAngleValue,false,mArcCirclePaint);

3)繪製文本

不同文本只是位置不一樣,計算好位置就可以繪製出文本了。

        //2-文本的位置:置中顯示        int centerX = width/2;        //計算文本寬度        int textWidth = (int) mTextPaint.measureText(mText, 0, mText.length());        //計算baseline:垂直方向置中        Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();        int baseline = (getMeasuredHeight() - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;        int textX = centerX-textWidth/2;        mTextPaint.setColor(mTextColor);        mTextPaint.setTextSize(mTextSize);        canvas.drawText(mText,textX,baseline,mTextPaint);        if (mTopText != null && !mTopText.equals("")) {            textWidth = (int) mTextPaint.measureText(mTopText, 0, mTopText.length());            textX = centerX - textWidth / 2;            mTextPaint.setTextSize(mTopTextSize);            mTextPaint.setColor(mTopTextColor);            canvas.drawText(mTopText, textX, baseline - 20, mTextPaint);        }        if (mBottomText != null && !mBottomText.equals("")) {            textWidth = (int) mTextPaint.measureText(mBottomText, 0, mBottomText.length());            textX = centerX - textWidth / 2;//            mTextPaint.reset();//            mTextPaint.setAntiAlias(true);//            mTextPaint.setLinearText(true);            mTextPaint.setTextSize(mTopTextSize);            mTextPaint.setColor(mBottomTextColor);            canvas.drawText(mBottomText, textX, baseline + 20, mTextPaint);        }

五、總結

其實很多的自訂View都是在畫布canvas中畫出來的,看著複雜(其實難在位置的計算),但是只要將其拆分成幾部分,一一畫出再組合就好了。

附上源碼:工程demo

package com.example.ViewDemo;import android.content.Context;import android.graphics.*;import android.util.AttributeSet;import android.view.View;/** * 自訂View方式三:重新繪製,繼承View * 第一步:畫出外圓drawArc * 第二步:畫出進度圓drawArc * 第三步:畫出文本:中間文本,頂部文本,底部文本drawText * Created by cjy on 17/6/14. */public class ArcCircleView extends View {    private Context mContext;    /**     * 文本畫筆     */    private Paint mTextPaint;    /**     * 圓弧畫筆     */    private Paint mArcCirclePaint;    /**     * 寬度     */    private float mWidth = 100.0f;    /**     * 文本     */    private String mText  ="0%";    /**     * 底部文本     */    private String mTopText  ="";    /**     * 底部文本     */    private String mBottomText  ="";    /**     * 弧度     */    private int mAngleValue = 0;    /**     * 圓的背景色:預設淺綠色     */    private int mCircleBackgroundColor = 0x4c11af9c;    /**     * 進度的顏色,預設白色     */    private int mProgressColor = 0xffffffff;    /**     * 頂部文本的顏色,預設白色     */    private int mTopTextColor = 0xffffffff;    /**     * 底部文本的顏色,預設白色     */    private int mBottomTextColor = 0xffffffff;    /**     * 文本的顏色,預設白色     */    private int mTextColor = 0xffffffff;    /**     * 邊寬     */    private int mStrokeWidth = 8;    /**     * 進度圓邊寬     */    private int mInnerStrokeWidth = 7;    /**     * 文字大小     */    private int mTextSize = 12;    /**     * 頂部文字大小     */    private int mTopTextSize = 10;    public ArcCircleView(Context context) {        super(context);        init(context);    }    public ArcCircleView(Context context, AttributeSet attrs) {        super(context, attrs);        init(context);    }    public ArcCircleView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init(context);    }    private void init(Context context){        mContext = context;        mTextPaint  = new Paint();        //設定消除鋸齒        mTextPaint.setAntiAlias(true);        //使文本看起來更清晰        mTextPaint.setLinearText(true);        mArcCirclePaint  = new Paint();        mArcCirclePaint.setAntiAlias(true);        mArcCirclePaint.setStyle(Paint.Style.STROKE);    }    public void setWidth(float width){        mWidth = width;        invalidate();    }    public void setText(String text){        mText = text;        invalidate();    }    public void setTopText(String text){        mTopText = text;        invalidate();    }    public void setBottomText(String text){        mBottomText = text;        invalidate();    }    public void setTextColor(int textColor) {        this.mTextColor = mContext.getResources().getColor(textColor);        invalidate();    }    public void setBottomTextColor(int bottomTextColor) {        this.mBottomTextColor = mContext.getResources().getColor(bottomTextColor);        invalidate();    }    public void setTopTextColor(int topTextColor) {        this.mTopTextColor = mContext.getResources().getColor(topTextColor);        invalidate();    }    public void setProgressColor(int progressColor) {        this.mProgressColor = mContext.getResources().getColor(progressColor);        invalidate();    }    public void setCircleBackgroundColor(int circleBackgroundColor) {        this.mCircleBackgroundColor = mContext.getResources().getColor(circleBackgroundColor);        invalidate();    }    public void setStrokeWidth(int strokeWidth){        this.mStrokeWidth = strokeWidth;        invalidate();    }    public void setInnerStrokeWidth(int innerStrokeWidth){        this.mInnerStrokeWidth = innerStrokeWidth;        invalidate();    }    public void setTextSize(int textSize){        this.mTextSize = textSize;        invalidate();    }    public void setTopTextSize(int topTextSize){        this.mTopTextSize = topTextSize;        invalidate();    }    /**     * 設定進度     * @param progress     */    public void setProgress(float progress){        int angleValue = (int) ((progress * 1.0)/100 * 360);        if (angleValue != 0 && progress <= 100){            mAngleValue  = angleValue;            mText = String.valueOf(progress)+"%";        }        invalidate();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //1-圓弧的位置:整圓,再繪製進度圓弧        mArcCirclePaint.setColor(mCircleBackgroundColor);        mArcCirclePaint.setStrokeWidth(mStrokeWidth);        //螢幕寬度        int width = getMeasuredWidth();        RectF rectF = new RectF();        rectF.left = (width-mWidth)/2;//左上方X        rectF.top = mWidth*0.1f;//左上方Y        rectF.right = (width-mWidth)/2+mWidth;//右上方X        rectF.bottom = mWidth*0.9f;//右上方Y        if ((rectF.right - rectF.left) > (rectF.bottom- rectF.top)){//正方形矩形,保證畫出的圓不會變成橢圓            float space = (rectF.right - rectF.left) - (rectF.bottom- rectF.top);            rectF.left += space/2;            rectF.right -= space/2;        }        canvas.drawArc(rectF,270,360,false,mArcCirclePaint);//第2個參數:時鐘3點處為0度,逆時針為正方向        mArcCirclePaint.setColor(mProgressColor);        //設定邊角為圓        mArcCirclePaint.setStrokeCap(Paint.Cap.ROUND);        mArcCirclePaint.setStrokeWidth(mInnerStrokeWidth);        canvas.drawArc(rectF,270,mAngleValue,false,mArcCirclePaint);        //2-文本的位置:置中顯示        int centerX = width/2;        //計算文本寬度        int textWidth = (int) mTextPaint.measureText(mText, 0, mText.length());        //計算baseline:垂直方向置中        Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();        int baseline = (getMeasuredHeight() - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;        int textX = centerX-textWidth/2;        mTextPaint.setColor(mTextColor);        mTextPaint.setTextSize(mTextSize);        canvas.drawText(mText,textX,baseline,mTextPaint);        if (mTopText != null && !mTopText.equals("")) {            textWidth = (int) mTextPaint.measureText(mTopText, 0, mTopText.length());            textX = centerX - textWidth / 2;            mTextPaint.setTextSize(mTopTextSize);            mTextPaint.setColor(mTopTextColor);            canvas.drawText(mTopText, textX, baseline - 20, mTextPaint);        }        if (mBottomText != null && !mBottomText.equals("")) {            textWidth = (int) mTextPaint.measureText(mBottomText, 0, mBottomText.length());            textX = centerX - textWidth / 2;//            mTextPaint.reset();//            mTextPaint.setAntiAlias(true);//            mTextPaint.setLinearText(true);            mTextPaint.setTextSize(mTopTextSize);            mTextPaint.setColor(mBottomTextColor);            canvas.drawText(mBottomText, textX, baseline + 20, mTextPaint);        }    }}

  

 

Android繪製圓形進度條

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.