拒絕第三方--手把手教你自定義進度條

還在爲了一個小小的效果,依賴一個一個的第三方?

看着別人隨隨便便寫了一個自定義效果,自己卻除了666啥也做不了?

如果你認爲自己就是這樣,那麼,你要好好看一下這篇文章了!

進度條作爲移動開發的一個常用功能,相信你一定不陌生。本篇,我們要手動編寫一個簡單的進度條,模擬一下下載的效果。

一、效果

二、分析

自定義View,分析裏面的元素:

1、進度條背景顏色

2、進度條背景是否是實心

3、進度條的顏色

4、進度(文字)的顏色和字體大小

5、進度條的圓角大小

三、實現

1、自定義View類,繼承View

public class CustomProgressView extends View {

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

    public CustomProgressView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

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


    }

2、在attr文件中,定義樣式

    <declare-styleable name="CustomProgressView">
        <!--百分比文字大小-->
        <attr name="cp_percent_textsize" format="dimension"/>
        <!--百分比文字顏色-->
        <attr name="cp_percent_textcolor" format="color|integer"/>
        <!--進度條背景顏色-->
        <attr name="cp_background_color" format="color|integer"/>
        <!--進度條背景是否空心-->
        <attr name="cp_background_is_stroke" format="boolean"/>
        <!--進度條顏色-->
        <attr name="cp_progress_color" format="color|integer"/>
        <!--進度條圓角值-->
        <attr name="cp_rect_round" format="dimension"/>

    </declare-styleable>

定義元素,並賦予正確的屬性類型。

3、在構造方法中,調用obtainStyledAttributes方法,獲取自定義的style,並初始化個屬性,同時,初始化畫筆Paint

    private int     cp_percent_textsize     = 18;//百分比字體大小
    private int     cp_percent_textcolor    = 0xff009ACD;
    private int     cp_background_color     = 0xff636363;
    private int     cp_progress_color       = 0xff00C5CD;
    private boolean cp_background_is_stroke = true;
    private int     cp_rect_round           = 5;
    private Paint mPaint;
    private int   mCenterX;
    private int   mCenterY;

    private int progressCurrent = 0;
    private int progressMax     = 100;


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

        TypedArray typedArray = context.obtainStyledAttributes(R.styleable.CustomProgressView);
        cp_percent_textsize = (int) typedArray.getDimension(R.styleable.CustomProgressView_cp_percent_textsize, cp_percent_textsize);
        cp_percent_textcolor = typedArray.getColor(R.styleable.CustomProgressView_cp_percent_textcolor, cp_percent_textcolor);
        cp_background_color = typedArray.getColor(R.styleable.CustomProgressView_cp_background_color, cp_background_color);
        cp_progress_color = typedArray.getColor(R.styleable.CustomProgressView_cp_progress_color, cp_progress_color);
        cp_background_is_stroke = typedArray.getBoolean(R.styleable.CustomProgressView_cp_background_is_stroke, cp_background_is_stroke);
        cp_rect_round = (int) typedArray.getDimension(R.styleable.CustomProgressView_cp_rect_round, cp_rect_round);
        typedArray.recycle();

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    }

4、複寫最重要的方法onDraw

    @Override
    protected void onDraw(Canvas canvas) {
        mCenterX = getWidth() / 2;
        mCenterY = getHeight() / 2;

        drawHorProgress(mPaint, canvas);

    }

    private void drawHorProgress(Paint paint, Canvas canvas) {
        //畫背景
        paint.setColor(cp_background_color);
        if (cp_background_is_stroke) {
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(1);
        } else {
            paint.setStyle(Paint.Style.FILL);
        }

        canvas.drawRoundRect(new RectF(mCenterX - getWidth() / 2, mCenterY - getHeight() / 2,
                mCenterX + getWidth() / 2, mCenterY + getHeight() / 2), cp_rect_round, cp_rect_round, paint);

        //畫進度條
        paint.setColor(cp_progress_color);
        paint.setStyle(Paint.Style.FILL);

        canvas.drawRoundRect(new RectF(mCenterX - getWidth() / 2, mCenterY - getHeight() / 2,
                (int) (progressCurrent * getWidth() / progressMax), mCenterY + getHeight() / 2), cp_rect_round, cp_rect_round, paint);

        //畫文字
        paint.setColor(cp_percent_textcolor);
        paint.setTextSize(cp_percent_textsize);
        paint.setStyle(Paint.Style.FILL);
        String value_str = (int) (progressCurrent * 100 / progressMax) + "%";
        Rect rect = new Rect();
        paint.getTextBounds(value_str, 0, value_str.length(), rect);

        float textWidth = rect.width();
        float textHeight = rect.height();
        if (textWidth >= getWidth()) {
            textWidth = getWidth();
        }
        Paint.FontMetrics metrics = paint.getFontMetrics();
        float baseline = (getMeasuredHeight() - metrics.bottom + metrics.top) / 2 - metrics.top;
        canvas.drawText(value_str, mCenterX - textWidth / 2, baseline, paint);

    }

步驟:

1、想一下,其實很簡單。

        進度條背景和進度條,就是兩個圓角矩形疊加在一起。最後再把文字畫在矩形的中間位置。

2、找到View的中心點,getWidth / 2 , getHeight / 2。

3、畫背景。

        其實背景很簡單。固定的圓角矩形。left、top、right、bottom座標其實是固定的。根據中心點,很容易畫出來。

4、畫進度條。

        進度條是根據的進度值的變化實時刷新的。所以我們要定義一個當前進度progressCurrent和最大進度progressMax。

        爲什麼要定義最大進度?實際生產中,你要根據下載文件的總大小和當前已經下載的大小來計算進度,所以這個是要設置的。

        仔細分析,可以知道,在你畫進度條的時候,其實只有一個座標值是變化的,那就是 right 。你可以根據當前進度的百分比來計算當前精度下的 right 佔寬度的多少比例。

5、畫文字

        使文字居中的baseline是一個知識點,需要重點掌握。

6、給各屬性值設置setter和getter方法。

         這裏主要說一下,進度值的設定。

    public int getProgressCurrent() {
        return progressCurrent;
    }

    public void setProgressCurrent(int progressCurrent) {
        if (progressCurrent > progressMax) {
            this.progressCurrent = progressMax;
        } else {
            this.progressCurrent = progressCurrent;
        }
        postInvalidate();
    }

噹噹前進度超過最大進度時,當前進度設定爲最大進度。(當前進度爲100%的下一秒,就會出現超過最大進度的情況)

記得重新繪製View 調用postInvalidate();方法。

5、佈局

 <net.feelingtech.example_work.custom.ownprogress.CustomProgressView
        android:id="@+id/cpv_one"
        android:layout_width="match_parent"
        android:layout_height="15dp" />

6、跑起來

        mCustomProgressView = view.findViewById(R.id.cpv_one);
        mCustomProgressView.setProgressMax(100);
        mCustomProgressView.setCp_background_color(Color.parseColor("#A2CD5A"));
        mCustomProgressView.setCp_percent_textcolor(Color.RED);
        mCustomProgressView.setCp_rect_round(16);
        mCustomProgressView.setCp_background_is_stroke(false);
        mCustomProgressView.setCp_percent_textsize(30);

        view.findViewById(R.id.bt_start).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (progressCurrent != 0) {
                    progressCurrent = 0;
                    return;
                }
                mRunnable = new Runnable() {
                    @Override
                    public void run() {

                        progressCurrent += 1;
                        mCustomProgressView.setProgressCurrent(progressCurrent);
                        mHandler.postDelayed(mRunnable, 5);

                    }
                };
                mHandler.postDelayed(mRunnable, 1);
            }
        });

OVER ! ! !

 

 

                                                                          掃碼關注,共同進步

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章