1. 程式人生 > >Android自定義View--圓形進度條RoundProgress

Android自定義View--圓形進度條RoundProgress

要實現的效果

RoundProgress

需要知道的知識點

  • 字型的高度和寬度是怎麼測?
    字型的高度就是textSize的大小。
    字型的寬度怎麼測量呢?Paint畫筆中有測量字型寬度的api,如下:
    //測量字型的寬度
    float width = mPaint.measureText(mProgerss + "%");
  • 字型的原點在哪裡?
    預設在字型的左下角(在drawText中用到,我們必須要讓字型在控制元件中間)
  • 圓的半徑怎麼確定?
    例如我們要畫下圖黃色的圓

    這裡寫圖片描述
    那麼我們的半徑是紅色那段還是黑色那段呢?,如圖所示(黑色代表圓心到外切正方形的距離,紅色代表黑色線段距離減去圓形線寬的一半的距離)。
    答案是紅色那段

自定義控制元件第一步–自定義屬性

在values新建attrs.xml檔案,定義屬性,如下所示

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RoundProgress">
        <!--背景圓形顏色 -->
        <attr name="bgColor" format="color"/>
        <!--進度條顏色 -->
        <attr name
="roundColor" format="color"/>
<!--進度條及背景圓形的寬度 --> <attr name="roundWidth" format="dimension"/> <!--中心字型的大小 --> <attr name="roundTextSize" format="dimension"/> <!--中心字型的顏色 --> <attr name="roundTextColor" format="color"/>
</declare-styleable> </resources>

自定義控制元件第二步–繼承view

package rc.loveq.roundprogress;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

/**
 * Author:Rc
 * Csdn:http://blog.csdn.net/loveqrc
 * 0n 2016/12/12 16:36
 * Email:[email protected]
 */

public class RoundProgress extends View {
    private static final int DEFAULT_BG_COLOR = Color.GRAY;
    private static final int DEFAULT_ROUND_COLOR = Color.RED;
    private static final float DEFAULT_TEXT_SIZE = 16;
    private static final float DEFAULT_ROUND_WIDTH = 10;
    private static final int DEFAULT_TEXT_COLOR = Color.BLACK;
    private int mBgColor;
    private int mRoundColor;
    private float mTextSize;
    private float mRoundWidth;
    private int mTextColor;
    private Paint mPaint;
    private int mCenterY;
    private int mCenterX;
    private float mRadius;
    private RectF mRectF;
    private int mProgerss=0;

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

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

    public RoundProgress(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = getResources().obtainAttributes(attrs, R.styleable.RoundProgress);
        //拿到在xml配置的屬性,如果沒有配置,就使用預設的。
        mBgColor = a.getColor(R.styleable.RoundProgress_bgColor, DEFAULT_BG_COLOR);
        mRoundColor = a.getColor(R.styleable.RoundProgress_roundColor, DEFAULT_ROUND_COLOR);
        mTextSize = a.getDimension(R.styleable.RoundProgress_roundTextSize, DEFAULT_TEXT_SIZE);
        mRoundWidth = a.getDimension(R.styleable.RoundProgress_roundWidth, DEFAULT_ROUND_WIDTH);
        mTextColor = a.getColor(R.styleable.RoundProgress_roundTextColor, DEFAULT_TEXT_COLOR);
        a.recycle();//釋放資源
        init();//初始化畫筆
    }

    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.STROKE);
    }

    /**
     * 當layout大小變化後會回撥次方法
     * 通過這方法獲取寬高
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mCenterX = w/2;//控寬的中心點
        mCenterY = h/2;//控制元件高的中心點
        //防止寬高不一致
        int min = Math.min(mCenterX, mCenterY);
        //半徑
        mRadius = min-mRoundWidth/2;
        //為畫圓弧準備
        mRectF = new RectF(mCenterX-mRadius,mCenterY-mRadius,mCenterX+mRadius,mCenterY+mRadius);
    }

    @Override
    protected void onDraw(Canvas canvas) {
    //        super.onDraw(canvas); 我們自己來畫
        //1、先畫背景圓環
        mPaint.setColor(mBgColor);
        mPaint.setStrokeWidth(mRoundWidth);
        canvas.drawCircle(mCenterX, mCenterY,mRadius,mPaint);
        //2、畫動態圓弧
        mPaint.setColor(mRoundColor);
        canvas.drawArc(mRectF,0, (float) (3.6*mProgerss),false,mPaint);
        //3、畫中間的文字
        mPaint.setColor(mTextColor);
        mPaint.setStrokeWidth(0);//如果不設定回0,很難看
        mPaint.setTextSize(mTextSize);
        //測量字型的寬度
        float width = mPaint.measureText(mProgerss + "%");
        canvas.drawText(mProgerss+"%",mCenterX-width/2,mCenterY+mTextSize/2,mPaint);
    }
    public void setProgerss(int progerss){
        mProgerss=progerss;
        postInvalidate();
    }
}

自定義控制元件第三步–在佈局中使用

  • 在根節點宣告自定義名稱空間
   xmlns:app="http://schemas.android.com/apk/res-auto"
  • 引用控制元件
<rc.loveq.roundprogress.RoundProgress
        android:layout_marginTop="10dp"
        android:layout_marginLeft="10dp"
        android:id="@+id/rp"
        android:layout_width="160dp"
        android:layout_height="160dp"
        app:bgColor="@android:color/darker_gray"
        app:roundColor="@android:color/holo_red_dark"
        app:roundWidth="10dp"
        app:roundTextColor="#18b4ed"
        app:roundTextSize="16sp"
    />

下載地址

下載地址