1. 程式人生 > >自定義漂亮的進度條

自定義漂亮的進度條

最近在鴻洋的部落格上看到一個自定義的ProgressBar,在github上也看到了這種型別的Progress,地址為:https://github.com/daimajia/NumberProgressBar ,我第一反應就是,我自己能不能也寫一個呢,先上效果圖


ColorfulProgressBar.java

package com.cool.mylibrary.widget;

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

import com.cool.mylibrary.R;
import com.cool.mylibrary.utils.UIUtils;

/**
 * 漂亮的ProgressBar
 * Created by cool on 2016/9/14.
 */
public class ColorfulProgressBar extends View {

    private int mReachedColor;//進度條到達了的顏色
    private int mUnReachedColor;//進度條未到達的顏色
    private float mReachedHight;//進度條的到達的高度
    private float mUnReachedHight;//進度條未到達的高度
    private float mProgressTextOffset;
    private float mProgressTextSize;

    private Paint mReachPaint;//到達畫筆
    private Paint mUnReachPaint;//未到達畫筆
    private Paint mTextPaint;//文字畫筆
    private int width;
    private int hight;
    private int mCurrentProgress;
    private int mTotalProgress = 100;
    private int textWith;

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

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

    public ColorfulProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorfulProgressBar);
        mReachedColor = typedArray.getColor(R.styleable.ColorfulProgressBar_reachedColor, Color.parseColor("#DC143C"));
        mUnReachedColor = typedArray.getColor(R.styleable.ColorfulProgressBar_unReachedColor, Color.rgb(204, 204, 204));
        mReachedHight = typedArray.getDimension(R.styleable.ColorfulProgressBar_reachedHight, UIUtils.dp2px(context, 3.5f));
        mUnReachedHight = typedArray.getDimension(R.styleable.ColorfulProgressBar_unReachedHight, UIUtils.dp2px(context, 2.5f));
        mProgressTextOffset = typedArray.getDimension(R.styleable.ColorfulProgressBar_progressTextOffset, UIUtils.dp2px(context, 3.0f));
        mProgressTextSize = typedArray.getDimension(R.styleable.ColorfulProgressBar_progressTextSize, UIUtils.sp2px(context, 14.0f));

        init();
    }

    private void init() {
        mReachPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mReachPaint.setColor(mReachedColor);
        mReachPaint.setStrokeWidth(mReachedHight);

        mUnReachPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mUnReachPaint.setColor(mUnReachedColor);
        mUnReachPaint.setStrokeWidth(mUnReachedHight);

        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(mReachedColor);
        mTextPaint.setTextSize(mProgressTextSize);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawUnReachLine(canvas);
        drawText(canvas);
        drawReachLine(canvas);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        if (heightMode != MeasureSpec.EXACTLY) {
            float textHeight = mTextPaint.descent() - mTextPaint.ascent();
            int exceptHeight = (int) (getPaddingTop() + getPaddingBottom() + Math
                    .max(Math.max(mReachedHight,
                            mUnReachedHight), Math.abs(textHeight)));
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(exceptHeight, MeasureSpec.EXACTLY);

        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    /**
     * 畫文字
     *
     * @param canvas
     */
    private void drawText(Canvas canvas) {
        String text = mCurrentProgress * 100 / mTotalProgress + "%";
        Rect rect = new Rect();
        mTextPaint.getTextBounds(text, 0, text.length(), rect);
        textWith = rect.right - rect.left;
        int x = (int) (((float) mCurrentProgress / mTotalProgress) * width + mProgressTextOffset);
        int y =  hight/2 + (rect.bottom - rect.top)/2;

        if(x >= width-textWith){
            x = width - textWith;
        }

        canvas.drawText(text,x,y,mTextPaint);
    }


    /**
     * 畫未到達的直線
     *
     * @param canvas
     */
    private void drawUnReachLine(Canvas canvas) {
        float startX = 0;
        float startY = hight/2;
        float endX = width;
        float endY = hight/2;
        canvas.drawLine(startX, startY, endX, endY, mUnReachPaint);
    }

    /**
     * 畫到達了的直線
     *
     * @param canvas
     */
    private void drawReachLine(Canvas canvas) {
        float startX = 0;
        float startY = hight/2;
        float endX = ((float) mCurrentProgress / mTotalProgress) * width;
        float endY = hight/2;

        if(endX >= width-textWith){
            endX = width - textWith;
        }

        canvas.drawLine(startX, startY, endX, endY, mReachPaint);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        width = w;
        hight = h;
    }

    public void setProgress(int currentProgress) {
        mCurrentProgress = currentProgress;
        invalidate();
    }

    public void setMax(int totalProgress) {
        mTotalProgress = totalProgress;
    }
}
自定義的屬性attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ColorfulProgressBar">
        <attr name="reachedColor" format="color"/>
        <attr name="unReachedColor" format="color"/>
        <attr name="reachedHight" format="dimension"/>
        <attr name="unReachedHight" format="dimension"/>
        <attr name="progressTextOffset" format="dimension"/>
        <attr name="progressTextSize" format="dimension"/>
    </declare-styleable>
</resources>

最後還有一個工具類UIUtils
package com.cool.mylibrary.utils;

import android.content.Context;

/**
 * Created by cool on 2016/9/14.
 */
public class UIUtils {

    /**
     * dp轉px
     *
     * @param context
     * @param dp
     * @return
     */
    public static int dp2px(Context context, float dp) {
        float density = context.getResources().getDisplayMetrics().density;
        int px = (int) (dp * density + 0.5f);
        return px;
    }

    /**
     * px轉dp
     *
     * @param context
     * @param px
     * @return
     */
    public static int px2dp(Context context, float px) {
        float density = context.getResources().getDisplayMetrics().density;
        int dp = (int) (px / density + 0.5f);
        return dp;
    }

    /**
     * sp轉px
     * @param context
     * @param sp
     * @return
     */
    public static float sp2px(Context context, float sp) {
        final float scale = context.getResources().getDisplayMetrics().scaledDensity;
        return sp * scale;
    }

}


使用:

佈局檔案中:

    <com.cool.mylibrary.widget.ColorfulProgressBar
        xmlns:cool="http://schemas.android.com/apk/res-auto"
        android:id="@+id/ppb1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        cool:reachedColor="#FF1493" />

程式碼中:

prefectProgressBar = (ColorfulProgressBar) findViewById(R.id.ppb);
prefectProgressBar.setMax(100);


new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 20; i++) {
                    final int finalI = i;
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            prefectProgressBar.setProgress(finalI);
                        }
                    });
                    SystemClock.sleep(40);
                }
               }
        }).start();