1. 程式人生 > >我的Android進階之旅------>Android自定義View實現帶數字的進度條(NumberProgressBar)

我的Android進階之旅------>Android自定義View實現帶數字的進度條(NumberProgressBar)

今天在Github上面看到一個來自於 daimajia所寫的關於Android自定義View實現帶數字的進度條(NumberProgressBar)的精彩案例,在這裡分享給大家一起來學習學習!同時感謝daimajia的開源奉獻!

第一步、效果展示

圖1、藍色的進度條
藍色的進度條

圖2、紅色的進度條
紅色的進度條

圖3、多條顏色不同的進度條
多條顏色不同的進度條

圖4、多條顏色不同的進度條
多條顏色不同的進度條

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

第二步、自定義ProgressBar實現帶數字的進度條

0、專案結構

這裡寫圖片描述

如上圖所示:library專案為自定義的帶數字的進度條NumberProgressBar的具體實現,demo專案為示例專案以工程依賴的方式引用library專案,然後使用自定義的帶數字的進度條NumberProgressBar來做展示

這裡寫圖片描述
如上圖所示:自定義的帶數字的進度條的library專案的結構圖

這裡寫圖片描述
如上圖所示:demo專案的結構圖

1、繪製步驟分析

如上面幾幅圖形所示。這個進度條的可以分為以下三部分:
這裡寫圖片描述

  • reacherd area :表示當前進度值之前文字的進度條(長方形)
  • text area :表示當前進度值文字
  • unreacherd area :當前進度值文字之後的進度條(長方形)

按照上面的分析,我們要實現帶數字的進度條,只需要按照以下三個步驟繪製即可實現:
1、繪製reacherd area(當前進度值之前文字的進度條)
2、繪製text area(當前進度值文字)
3、繪製unreacherd area

(當前進度值文字之後的進度條) 即可。

2、自定義屬性

由於我們發現以上三個部分的顏色、字型大小、進度條的最大值、表示進度條的長方形的高度等屬性都可以改變,從而展現出不同的介面效果。

因此我們將這些屬性都做自定義屬性。這樣我們就能夠做到像android官方提供的那些元件一樣用xml來定義它的屬性了。

1、定義自己的屬性配置檔案:attr.xml

在res/values檔案下定義一個attrs.xml檔案,res/values/attrs.xml定義程式碼如下所示:

<?xml version="1.0" encoding="utf-8"?>
<resources
>
<declare-styleable name="NumberProgressBar"> <!--進度條的當前進度值--> <attr name="progress_current" format="integer"/> <!--進度條的最大進度值--> <attr name="progress_max" format="integer"/> <!--當前進度值文字之後的進度條顏色--> <attr name="progress_unreached_color" format="color"/> <!--當前進度值文字之前的進度條顏色--> <attr name="progress_reached_color" format="color"/> <!-- 當前進度值文字之前的進度條的高度--> <attr name="progress_reached_bar_height" format="dimension"/> <!--當前進度值文字之後的進度條的高度--> <attr name="progress_unreached_bar_height" format="dimension"/> <!--當前進度值文字的字型大小--> <attr name="progress_text_size" format="dimension"/> <!--當前進度值文字的顏色--> <attr name="progress_text_color" format="color"/> <!--當前進度值之前文字的間距--> <attr name="progress_text_offset" format="dimension"/> <!--當前進度值文字是否可見--> <attr name="progress_text_visibility" format="enum"> <enum name="visible" value="0"/> <enum name="invisible" value="1"/> </attr> </declare-styleable> <declare-styleable name="Themes"> <attr name="numberProgressBarStyle" format="reference"/> </declare-styleable> </resources>

2、定義主題配置檔案:styles.xml

在res/values檔案下定義一個styles.xml檔案,裡面定義一些基本的主題選項,以備使用者可以選擇使用。res/values/styles.xml定義程式碼如下所示:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="NumberProgressBar_Default">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">match_parent</item>

        <item name="progress_max">100</item>
        <item name="progress_current">0</item>

        <item name="progress_unreached_color">#CCCCCC</item>
        <item name="progress_reached_color">#3498DB</item>

        <item name="progress_text_size">10sp</item>
        <item name="progress_text_color">#3498DB</item>

        <item name="progress_reached_bar_height">1.5dp</item>
        <item name="progress_unreached_bar_height">0.75dp</item>
    </style>

    <style name="NumberProgressBar_Passing_Green">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">match_parent</item>

        <item name="progress_max">100</item>
        <item name="progress_current">0</item>

        <item name="progress_unreached_color">#CCCCCC</item>
        <item name="progress_reached_color">#70A800</item>

        <item name="progress_text_size">10sp</item>
        <item name="progress_text_color">#70A800</item>

        <item name="progress_reached_bar_height">1.5dp</item>
        <item name="progress_unreached_bar_height">0.75dp</item>
    </style>

    <style name="NumberProgressBar_Beauty_Red">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">match_parent</item>

        <item name="progress_max">100</item>
        <item name="progress_current">0</item>

        <item name="progress_unreached_color">#CCCCCC</item>
        <item name="progress_reached_color">#FF3D7F</item>
        <item name="progress_text_size">10sp</item>
        <item name="progress_text_color">#FF3D7F</item>

        <item name="progress_reached_bar_height">1.5dp</item>
        <item name="progress_unreached_bar_height">0.75dp</item>
    </style>

    <style name="NumberProgressBar_Warning_Red">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">match_parent</item>

        <item name="progress_max">100</item>
        <item name="progress_current">0</item>

        <item name="progress_unreached_color">#CCCCCC</item>
        <item name="progress_reached_color">#E74C3C</item>
        <item name="progress_text_size">10sp</item>
        <item name="progress_text_color">#E74C3C</item>

        <item name="progress_reached_bar_height">1.5dp</item>
        <item name="progress_unreached_bar_height">0.75dp</item>
    </style>

    <style name="NumberProgressBar_Relax_Blue">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">match_parent</item>

        <item name="progress_max">100</item>
        <item name="progress_current">0</item>

        <item name="progress_unreached_color">#CCCCCC</item>
        <item name="progress_reached_color">#6DBCDB</item>
        <item name="progress_text_size">10sp</item>
        <item name="progress_text_color">#6DBCDB</item>

        <item name="progress_reached_bar_height">1.5dp</item>
        <item name="progress_unreached_bar_height">0.75dp</item>
    </style>

    <style name="NumberProgressBar_Grace_Yellow">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">match_parent</item>

        <item name="progress_max">100</item>
        <item name="progress_current">0</item>

        <item name="progress_unreached_color">#CCCCCC</item>
        <item name="progress_reached_color">#FFC73B</item>
        <item name="progress_text_size">10sp</item>
        <item name="progress_text_color">#FFC73B</item>

        <item name="progress_reached_bar_height">1.5dp</item>
        <item name="progress_unreached_bar_height">0.75dp</item>
    </style>

    <style name="NumberProgressBar_Funny_Orange">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">match_parent</item>

        <item name="progress_max">100</item>
        <item name="progress_current">0</item>

        <item name="progress_unreached_color">#CCCCCC</item>
        <item name="progress_reached_color">#FF530D</item>
        <item name="progress_text_size">10sp</item>
        <item name="progress_text_color">#FF530D</item>

        <item name="progress_reached_bar_height">1.5dp</item>
        <item name="progress_unreached_bar_height">0.75dp</item>
    </style>

    <style name="NumberProgressBar_Twinkle_Night">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">match_parent</item>

        <item name="progress_max">100</item>
        <item name="progress_current">0</item>

        <item name="progress_unreached_color">#CCCCCC</item>
        <item name="progress_reached_color">#ECF0F1</item>
        <item name="progress_text_size">10sp</item>
        <item name="progress_text_color">#ECF0F1</item>

        <item name="progress_reached_bar_height">1.5dp</item>
        <item name="progress_unreached_bar_height">0.75dp</item>
    </style>
</resources>

3、自定義View實現帶數字的進度條

package com.daimajia.numberprogressbar;

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.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.View;

import static com.daimajia.numberprogressbar.NumberProgressBar.ProgressTextVisibility.Invisible;
import static com.daimajia.numberprogressbar.NumberProgressBar.ProgressTextVisibility.Visible;

/**
 * Created by daimajia on 14-4-30.
 */
public class NumberProgressBar extends View {
    /**
     * 進度值最大值
     */
    private int mMaxProgress = 100;

    /**
     * Current progress, can not exceed the max progress.
     * 當前進度值,不能超過進度值最大值
     */
    private int mCurrentProgress = 0;

    /**
     * The progress area bar color.
     * 當前進度值文字之前的進度條顏色
     */
    private int mReachedBarColor;

    /**
     * The bar unreached area color.
     * 當前進度值文字之後的進度條顏色
     */
    private int mUnreachedBarColor;

    /**
     * The progress text color.
     * 當前進度值文字的顏色
     */
    private int mTextColor;

    /**
     * The progress text size.
     * 當前進度值文字的字型大小
     */
    private float mTextSize;

    /**
     * The height of the reached area.
     * 當前進度值文字之前的進度條的高度
     */
    private float mReachedBarHeight;

    /**
     * The height of the unreached area.
     * 當前進度值文字之後的進度條的高度
     */
    private float mUnreachedBarHeight;

    /**
     * The suffix of the number.
     * 當前進度值的百分比字尾
     */
    private String mSuffix = "%";

    /**
     * The prefix.
     * 當前進度值的百分比字首
     */
    private String mPrefix = "";

    //當前進度值文字的預設顏色
    private final int default_text_color = Color.rgb(66, 145, 241);
    //當前進度值文字的字型大小
    private final float default_text_size;

    //當前進度值之前的預設進度條顏色
    private final int default_reached_color = Color.rgb(66, 145, 241);
    //當前進度值之後的預設進度條顏色
    private final int default_unreached_color = Color.rgb(204, 204, 204);

    //當前進度值之前文字的預設間距
    private final float default_progress_text_offset;

    //當前進度值文字之前的進度條的預設高度
    private final float default_reached_bar_height;
    //當前進度值文字之後的進度條的預設高度
    private final float default_unreached_bar_height;

    /**
     * For save and restore instance of progressbar.
     */
    private static final String INSTANCE_STATE = "saved_instance";
    private static final String INSTANCE_TEXT_COLOR = "text_color";
    private static final String INSTANCE_TEXT_SIZE = "text_size";
    private static final String INSTANCE_REACHED_BAR_HEIGHT = "reached_bar_height";
    private static final String INSTANCE_REACHED_BAR_COLOR = "reached_bar_color";
    private static final String INSTANCE_UNREACHED_BAR_HEIGHT = "unreached_bar_height";
    private static final String INSTANCE_UNREACHED_BAR_COLOR = "unreached_bar_color";
    private static final String INSTANCE_MAX = "max";
    private static final String INSTANCE_PROGRESS = "progress";
    private static final String INSTANCE_SUFFIX = "suffix";
    private static final String INSTANCE_PREFIX = "prefix";
    private static final String INSTANCE_TEXT_VISIBILITY = "text_visibility";
    //預設顯示當前進度值文字   0為顯示,1為不顯示
    private static final int PROGRESS_TEXT_VISIBLE = 0;


    /**
     * The width of the text that to be drawn.
     * 要繪製的當前進度值的文字的寬度
     */
    private float mDrawTextWidth;

    /**
     * The drawn text start.
     * 要繪製的當前進度值的文字的起始位置
     */
    private float mDrawTextStart;

    /**
     * The drawn text end.
     * 要繪製的當前進度值的文字的結束位置
     */
    private float mDrawTextEnd;

    /**
     * The text that to be drawn in onDraw().
     * 要繪製的當前進度值的文字
     */
    private String mCurrentDrawText;

    /**
     * The Paint of the reached area.
     * 繪製當前進度值文字之前的進度條的畫筆
     */
    private Paint mReachedBarPaint;
    /**
     * The Paint of the unreached area.
     * 繪製當前進度值文字之後的進度條的畫筆
     */
    private Paint mUnreachedBarPaint;
    /**
     * The Paint of the progress text.
     * 繪製當前進度值文字的的畫筆
     */
    private Paint mTextPaint;

    /**
     * Unreached bar area to draw rect.
     * 當前進度值文字之後的進度條(長方形)
     */
    private RectF mUnreachedRectF = new RectF(0, 0, 0, 0);
    /**
     * Reached bar area rect.
     * 當前進度值之前文字的進度條(長方形)
     */
    private RectF mReachedRectF = new RectF(0, 0, 0, 0);

    /**
     * The progress text offset.
     * 當前進度值之前文字的間距
     */
    private float mOffset;

    /**
     * Determine if need to draw unreached area.
     * 是否繪製當前進度值之後的進度條
     */
    private boolean mDrawUnreachedBar = true;
    /**
     * 是否繪製當前進度值之前的進度條
     */
    private boolean mDrawReachedBar = true;
    /**
     * 是否繪製當前進度值文字
     */
    private boolean mIfDrawText = true;

    /**
     * Listener
     */
    private OnProgressBarListener mListener;

    public enum ProgressTextVisibility {
        Visible, Invisible
    }

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

    public NumberProgressBar(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.numberProgressBarStyle);
    }

    public NumberProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        default_reached_bar_height = dp2px(1.5f);
        default_unreached_bar_height = dp2px(1.0f);
        default_text_size = sp2px(10);
        default_progress_text_offset = dp2px(3.0f);

        //獲取自定義屬性
        final TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.NumberProgressBar,
                defStyleAttr, 0);
        mReachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_reached_color, default_reached_color);
        mUnreachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_unreached_color, default_unreached_color);
        mTextColor = attributes.getColor(R.styleable.NumberProgressBar_progress_text_color, default_text_color);
        mTextSize = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_size, default_text_size);

        mReachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_reached_bar_height, default_reached_bar_height);
        mUnreachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_unreached_bar_height, default_unreached_bar_height);
        mOffset = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_offset, default_progress_text_offset);

        int textVisible = attributes.getInt(R.styleable.NumberProgressBar_progress_text_visibility, PROGRESS_TEXT_VISIBLE);

        if (textVisible != PROGRESS_TEXT_VISIBLE) {
            mIfDrawText = false;
        }

        setProgress(attributes.getInt(R.styleable.NumberProgressBar_progress_current, 0));
        setMax(attributes.getInt(R.styleable.NumberProgressBar_progress_max, 100));
        //回收 TypedArray,用於後續呼叫時可複用之。回收到TypedArrayPool池中,以備後用
        attributes.recycle();
        initializePainters();
    }

    @Override
    protected int getSuggestedMinimumWidth() {
        return (int) mTextSize;
    }

    @Override
    protected int getSuggestedMinimumHeight() {
        return Math.max((int) mTextSize, Math.max((int) mReachedBarHeight, (int) mUnreachedBarHeight));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        /**
         * MeasureSpec引數的值為int型,分為高32位和低16為,
         * 高32位儲存的是specMode,低16位表示specSize,
         *
         * specMode分三種:
         1、MeasureSpec.UNSPECIFIED,父檢視不對子檢視施加任何限制,子檢視可以得到任意想要的大小;
         2、MeasureSpec.EXACTLY,父檢視希望子檢視的大小是specSize中指定的大小;
         3、MeasureSpec.AT_MOST,子檢視的大小最多是specSize中的大小。
         */
        setMeasuredDimension(measure(widthMeasureSpec, true), measure(heightMeasureSpec, false));
    }

    private int measure(int measureSpec, boolean isWidth) {

        int result;
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        int padding = isWidth ? getPaddingLeft() + getPaddingRight() : getPaddingTop() + getPaddingBottom();
        /**
         父決定子的確切大小,子被限定在給定的邊界裡,忽略本身想要的大小。
         (當設定width或height為match_parent時,模式為EXACTLY,因為子view會佔據剩餘容器的空間,所以它大小是確定的)
         */
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        } else {
            result = isWidth ? getSuggestedMinimumWidth() : getSuggestedMinimumHeight();
            result += padding;
            /**
             *子最大可以達到的指定大小
             * (當設定為wrap_content時,模式為AT_MOST, 表示子view的大小最多是多少,這樣子view會根據這個上限來設定自己的尺寸)
             */
            if (mode == MeasureSpec.AT_MOST) {
                if (isWidth) {
                    result = Math.max(result, size);
                } else {
                    result = Math.min(result, size);
                }
            }
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //如果要繪製當前進度值文字
        if (mIfDrawText) {
            calculateDrawRectF();
        }else {
            calculateDrawRectFWithoutProgressText();
        }

        //如果要繪製當前進度值之前的進度條
        if (mDrawReachedBar) {
            canvas.drawRect(mReachedRectF, mReachedBarPaint);
        }

        //如果要繪製當前進度值之後的進度條
        if (mDrawUnreachedBar) {
            canvas.drawRect(mUnreachedRectF, mUnreachedBarPaint);
        }

        //繪製當前進度值文字
        if (mIfDrawText)
            canvas.drawText(mCurrentDrawText, mDrawTextStart, mDrawTextEnd, mTextPaint);
    }

    /**
     * 初始化畫筆
     */
    private void initializePainters() {
        mReachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mReachedBarPaint.setColor(mReachedBarColor);

        mUnreachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mUnreachedBarPaint.setColor(mUnreachedBarColor);

        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(mTextColor);
        mTextPaint.setTextSize(mTextSize);
    }

    /**
     * 計算不要繪製當前進度值文字時 圖形的各個屬性
     */
    private void calculateDrawRectFWithoutProgressText() {
        //當前進度值不畫

        //當前進度值之前的進度條(長方形)的屬性
        mReachedRectF.left = getPaddingLeft();
        mReachedRectF.top = getHeight() / 2.0f - mReachedBarHeight / 2.0f;
        mReachedRectF.right =
                (getWidth() - getPaddingLeft() - getPaddingRight()) / (getMax() * 1.0f) * getProgress()
                        + getPaddingLeft();
        mReachedRectF.bottom = getHeight() / 2.0f + mReachedBarHeight / 2.0f;

        //當前進度值之後的進度條(長方形)的屬性
        mUnreachedRectF.left = mReachedRectF.right;
        mUnreachedRectF.right = getWidth() - getPaddingRight();
        mUnreachedRectF.top = getHeight() / 2.0f + -mUnreachedBarHeight / 2.0f;
        mUnreachedRectF.bottom = getHeight() / 2.0f + mUnreachedBarHeight / 2.0f;
    }

    /**
     * 計算要繪製當前進度值文字時 圖形的各個屬性
     */
    private void calculateDrawRectF() {
        //要繪製的當前進度值的文字
        mCurrentDrawText = String.format("%d", getProgress() * 100 / getMax());
        mCurrentDrawText = mPrefix + mCurrentDrawText + mSuffix;
        //要繪製的當前進度值的文字的寬度
        mDrawTextWidth = mTextPaint.measureText(mCurrentDrawText);
        //如果當前進度值為0,則不繪製當前進度值之前的進度條
        if (getProgress() == 0) {
            mDrawReachedBar = false;
            mDrawTextStart = getPaddingLeft();
        }
        //否則繪製當前進度值文字之前的進度條
        else {
            mDrawReachedBar = true;
            //當前進度值文字之前的進度條(長方形)的屬性
            mReachedRectF.left = getPaddingLeft();
            mReachedRectF.top = getHeight() / 2.0f - mReachedBarHeight / 2.0f;
            mReachedRectF.right= (getWidth() - getPaddingLeft() - getPaddingRight()) / (getMax() * 1.0f) * getProgress()
                    - mOffset + getPaddingLeft();
            mReachedRectF.bottom = getHeight() / 2.0f + mReachedBarHeight / 2.0f;
            //當前進度值的文字的起始位置
            mDrawTextStart = (mReachedRectF.right + mOffset);
        }
        //當前進度值的文字的結束位置
        mDrawTextEnd = (int) ((getHeight() / 2.0f) - ((mTextPaint.descent() + mTextPaint.ascent()) / 2.0f));
        //如果畫不下當前進度值的文字了,就重新計算下當前進度值的文字的起始位置和當前進度值之前的進度條(長方形)的右邊
        if ((mDrawTextStart + mDrawTextWidth) >= getWidth() - getPaddingRight()) {
            mDrawTextStart = getWidth() - getPaddingRight() - mDrawTextWidth;
            mReachedRectF.right = mDrawTextStart - mOffset;
        }

        //當前進度值文字之後的進度條的起始位置
        float unreachedBarStart = mDrawTextStart + mDrawTextWidth + mOffset;
        //如果畫不下進度值文字之後的進度條了,就不畫進度值之後的進度條
        if (unreachedBarStart >= getWidth() - getPaddingRight()) {
            mDrawUnreachedBar = false;
        } else {
            mDrawUnreachedBar = true;
            //當前進度值文字之後的進度條(長方形)的屬性
            mUnreachedRectF.left = unreachedBarStart;
            mUnreachedRectF.right = getWidth() - getPaddingRight();
            mUnreachedRectF.top = getHeight() / 2.0f + -mUnreachedBarHeight / 2.0f;
            mUnreachedRectF.bottom = getHeight() / 2.0f + mUnreachedBarHeight / 2.0f;
        }
    }

    /**
     * Get progress text color.
     * 獲取當前進度值文字的顏色
     * @return progress text color.
     */
    public int getTextColor() {
        return mTextColor;
    }

    /**
     * Get progress text size.
     * 獲取當前進度值文字的字型大小
     * @return progress text size.
     */
    public float getProgressTextSize() {
        return mTextSize;
    }

    /**
     * 獲取當前進度值文字之後的進度條顏色
     */
    public int getUnreachedBarColor() {
        return mUnreachedBarColor;
    }

    /**
     * 獲取當前進度值文字之前的進度條顏色
     */
    public int getReachedBarColor() {
        return mReachedBarColor;
    }
    /**
     * 獲取進度條的當前進度值
     */
    public int getProgress() {
        return mCurrentProgress;
    }
    /**
     * 獲取進度條的最大值
     */
    public int getMax() {
        return mMaxProgress;
    }
    /**
     * 獲取當前進度值文字之前的進度條的高度
     */
    public float getReachedBarHeight() {
        return mReachedBarHeight;
    }
    /**
     * 獲取當前進度值文字之後的進度條的高度
     */
    public float getUnreachedBarHeight() {
        return mUnreachedBarHeight;
    }
    /**
     * 設定當前進度值文字的字型大小
     * @param textSize 當前進度值文字的字型大小
     */
    public void setProgressTextSize(float textSize) {
        this.mTextSize = textSize;
        mTextPaint.setTextSize(mTextSize);
        invalidate();
    }
    /**
     * 設定當前進度值文字的顏色
     * @param textColor 當前進度值文字的顏色
     */
    public void setProgressTextColor(int textColor) {
        this.mTextColor = textColor;
        mTextPaint.setColor(mTextColor);
        invalidate();
    }
    /**
     * 設定當前進度值文字之後的進度條顏色
     * @param barColor 當前進度值文字之後的進度條顏色
     */
    public void setUnreachedBarColor(int barColor) {
        this.mUnreachedBarColor = barColor;
        mUnreachedBarPaint.setColor(mUnreachedBarColor);
        invalidate();
    }
    /**
     * 設定當前進度值文字之前的進度條顏色
     * @param progressColor 當前進度值文字之前的進度條顏色
     */
    public void setReachedBarColor(int progressColor) {
        this.mReachedBarColor = progressColor;
        mReachedBarPaint.setColor(mReachedBarColor);
        invalidate();
    }
    /**
     * 設定當前進度值文字之前的進度條的高度
     * @param height 當前進度值文字之前的進度條的高度
     */
    public void setReachedBarHeight(float height) {
        mReachedBarHeight = height;
    }
    /**
     * 設定當前進度值文字之後的進度條的高度
     * @param height 當前進度值文字之後的進度條的高度
     */
    public void setUnreachedBarHeight(float height) {
        mUnreachedBarHeight = height;
    }

    /**
     * 設定進度值的最大值
     * @param maxProgress 進度值的最大值
     */
    public void setMax(int maxProgress) {
        if (maxProgress > 0) {
            this.mMaxProgress = maxProgress;
            invalidate();
        }
    }
    /**
     * 設定當前進度值文字的字尾
     * @param suffix 當前進度值文字的字尾
     */
    public void setSuffix(String suffix) {
        if (suffix == null) {
            mSuffix = "";
        } else {
            mSuffix = suffix;
        }
    }
    /**
     * 獲取當前進度值文字的字尾
     */
    public String getSuffix() {
        return mSuffix;
    }
    /**
     * 設定當前進度值文字的字首
     * @param prefix 當前進度值文字的字首
     */
    public void setPrefix(String prefix) {
        if (prefix == null)
            mPrefix = "";
        else {
            mPrefix = prefix;
        }
    }
    /**
     * 獲取當前進度值文字的字首
     */
    public String getPrefix() {
        return mPrefix;
    }

    /**
     * 設定進度條的當前進度值增加
     * @param by 增加多少
     */
    public void incrementProgressBy(int by) {
        if (by > 0) {
            setProgress(getProgress() + by);
        }
        if (mListener != null) {
            //回撥onProgressChange()方法來處理進度值變化後的事件
            mListener.onProgressChange(getProgress(), getMax());
        }
    }

    /**
     * 設定當前進度值
     *
     * @param progress 當前進度值
     */
    public void setProgress(int progress) {
        if (progress <= getMax() && progress >= 0) {
            this.mCurrentProgress = progress;
            invalidate();
        }
    }

    @Override
    protected Parcelable onSaveInstanceStat