1. 程式人生 > >Android之自定義可顯示分段顏色的progressBar

Android之自定義可顯示分段顏色的progressBar

本文主要記錄一個自定義progressBar,主要是實現分段顯示不同顏色的ProgressBar




重點為了記錄一下自定義view的過程

1.新建一個class,繼承View或其子類,具體可以繼承哪些類,看這篇,比如類名叫 ProgressbarView ;

2. 編寫屬性檔案,放在values裡,在佈局裡使用時都是需要設定一些相關屬性的,比如

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ProgressbarView">
        <attr name="p_width" format="dimension"/> <!-- 控制元件寬度 -->
        <attr name="p_height" format="dimension"/><!-- 控制元件官高度 -->
        <attr name="p_maxValue" format="integer"/><!-- 控制元件progress最大值 -->
        <attr name="p_progressValue" format="integer"/><!--  當前 progress value -->
        <attr name="p_shapeType" format="enum"><!-- 控制元件型別 矩形,圓,圓角矩形 -->
            <enum name="rectangle" value="0" />
            <enum name="circle" value="1" />
            <enum name="square" value="2" />
        </attr>
        <attr name="p_progressColor" format="color"/><!-- progress 進度條顏色 -->
        <attr name="p_progressBackColor" format="color"/><!-- progress 背景 顏色 -->
        <attr name="p_progressSegmentColor" format="color"/><!-- progress 分段 顏色 -->
        <attr name="p_progressDoubleSegColor" format="color"/><!-- progress 分段間隔 顏色 -->
        <attr name="p_circle_radius" format="dimension"/><!-- 圓 半徑 -->
        <attr name="p_circle_X_Y" format="dimension"/><!-- 圓 心 橫座標或者縱座標 > 半徑(正方形嘛)-->
        <attr name="p_showText" format="boolean"/><!-- 是否顯示文字 -->
        <attr name="p_textSize" format="dimension"/><!-- 文字大小 -->
        <attr name="p_textLowColor" format="color"/><!-- 1/3 文字顏色 -->
        <attr name="p_textMiddleColor" format="color"/><!-- 1/3 - 2/3文字顏色 -->
        <attr name="p_textHighColor" format="color"/><!-- 2/3文字顏色 -->
        <attr name="p_square_radius" format="dimension"/><!-- 圓角矩形 半徑-->

    </declare-styleable>

</resources>
<declare-styleable name="ProgressbarView">裡的name是檔案類名,attr裡是屬性名,佈局檔案裡會這麼使用
    <com.cl.slack.lib.ProgressbarView
        android:id="@+id/progressbar"
        android:layout_width="wrap_content"
        android:layout_height="100dp"
        app:p_height = "10dp"
        app:p_width = "300dp"
        app:p_shapeType="square"
        app:p_progressColor="#00ff00"
        app:p_progressBackColor="#777777"
        app:p_progressSegmentColor="#008800"
        app:p_progressDoubleSegColor="#770077"
        app:p_showText = "true"
        app:p_square_radius="8dp"
        app:p_textSize="13sp"
        app:p_textLowColor="#880055"
        app:p_textMiddleColor="#008855"
        app:p_textHighColor="#885500"
        app:p_circle_radius="20dp"
        app:p_circle_X_Y="30dp"
        />
然後這個檔案在java程式碼裡怎麼使用呢,在我們的view裡,我們需要實現其構造方法,有三個,AttributeSet物件就是用來處理自定義屬性的,直接上程式碼
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.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>Description:  progressbar </p>
 * Created by slack on 2016/8/1 10:04 .
 */
public class ProgressbarView extends View {

    private final int DEFAULT_WIDTH = 450;
    private final int DEFAULT_HEIGTH = 40;
    private final int DEFAULT_SHAPE = 0;
    private final int DEFAULT_MAX = 100;
    private final int DEFAULT_PROGRESS = 0;
    private final int DEFAULT_PROGRESS_COLOR = Color.parseColor("#76B034");
    private final int DEFAULT_PROGRESS_BACK_COLOR = Color.parseColor("#EFEFEF");
    private final int DEFAULT_CIRCLE_R = 50;
    private final int DEFAULT_SQUARE_R = 20;
    private final int DEFAULT_TEXT_SIZE = 30;

    private enum ShapeType{
        RECTANGLE,
        CIRCLE,
        SQUARE
    }

    private int progress = DEFAULT_PROGRESS;
    private int max = DEFAULT_MAX;
    private float mwidth = DEFAULT_WIDTH;
    private float mhight = DEFAULT_HEIGTH;
    private int mShapeType = DEFAULT_SHAPE;
    private int proColor = DEFAULT_PROGRESS_COLOR;
    private int proBackColor = DEFAULT_PROGRESS_BACK_COLOR;
    private int textLowColor = Color.BLACK;
    private int textMiddleColor = Color.BLUE;
    private int textHighColor = Color.RED;
    private int progressSegmentColor = proColor;
    private int progressDoubleSegColor = Color.GRAY;

    private float squareRadius = DEFAULT_SQUARE_R;
    private float textSize = DEFAULT_TEXT_SIZE;

    private boolean showText;
    private float circleX = DEFAULT_CIRCLE_R + 20;
    private float circleR = DEFAULT_CIRCLE_R;

    private float startX;
    private float startY;
    private float startR = -90;
    private Paint paint;
    RectF circleRectf,squareRectf;
    private List<Integer> progressList;
    
    public ProgressbarView(Context context) {
        this(context,null);
    }

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

    public ProgressbarView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs, defStyleAttr);
    }

    private void initView(Context context, AttributeSet attrs, int defStyleAttr) {
        // Load the styled attributes and set their properties
        TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.ProgressbarView, defStyleAttr, 0);
        mwidth = attributes.getDimension(R.styleable.ProgressbarView_p_width, DEFAULT_WIDTH);
        mhight = attributes.getDimension(R.styleable.ProgressbarView_p_height, DEFAULT_HEIGTH);
        mShapeType = attributes.getInteger(R.styleable.ProgressbarView_p_shapeType, DEFAULT_SHAPE);
        showText = attributes.getBoolean(R.styleable.ProgressbarView_p_showText,false);

        if(mShapeType == 1){
            circleR = attributes.getDimension(R.styleable.ProgressbarView_p_circle_radius, DEFAULT_CIRCLE_R);
//            showText = true;
            circleX = attributes.getDimension(R.styleable.ProgressbarView_p_circle_X_Y,circleR + 20);
        }
        if(mShapeType == 2){
            squareRadius = attributes.getDimension(R.styleable.ProgressbarView_p_square_radius,DEFAULT_SQUARE_R);
        }

        if(showText){
            textSize = attributes.getDimensionPixelSize(R.styleable.ProgressbarView_p_textSize,DEFAULT_TEXT_SIZE);
        }
        max = attributes.getInteger(R.styleable.ProgressbarView_p_maxValue, DEFAULT_MAX);
        progress = attributes.getInteger(R.styleable.ProgressbarView_p_progressValue, DEFAULT_PROGRESS);
        proColor = attributes.getColor(R.styleable.ProgressbarView_p_progressColor,DEFAULT_PROGRESS_COLOR);
        proBackColor = attributes.getColor(R.styleable.ProgressbarView_p_progressBackColor,DEFAULT_PROGRESS_BACK_COLOR);
        textLowColor = attributes.getColor(R.styleable.ProgressbarView_p_textLowColor,Color.BLACK);
        textMiddleColor = attributes.getColor(R.styleable.ProgressbarView_p_textMiddleColor,Color.BLUE);
        textHighColor = attributes.getColor(R.styleable.ProgressbarView_p_textHighColor,Color.RED);
        progressSegmentColor = attributes.getColor(R.styleable.ProgressbarView_p_progressSegmentColor,DEFAULT_PROGRESS_COLOR);
        progressDoubleSegColor = attributes.getColor(R.styleable.ProgressbarView_p_progressDoubleSegColor,Color.GRAY);

        Log.i("slack",mwidth + "," + mhight + "," +  mShapeType + "," +  max + "," +
                progress + "," + showText + "," + squareRadius + "," + textSize);
        paint = new Paint();
        circleRectf = new RectF();
        squareRectf = new RectF();
        progressList = new ArrayList<>();

        paint.setAntiAlias(true);
        paint.setFlags(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.parseColor("#EFEFEF"));
        paint.setStrokeWidth(10);
//        paint.setStyle(Paint.Style.STROKE);
        paint.setStyle(Paint.Style.FILL);


    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        paint.setColor(proBackColor);
        paint.setStrokeWidth(10);
        paint.setTextSize(textSize);
        startX = 0;
        startY = 0;

        switch (mShapeType){
            case 0:
                canvas.drawRect(startX, startY, mwidth, mhight, paint);
                paint.setColor(proColor);
                if(progressList.size() > 0){
                    for(int pro : progressList){
                        canvas.drawRect(startX, startY, ((float) pro / max) * mwidth,
                                mhight, paint);
                        startX = ((float) pro/max) * mwidth;
//                        Log.i("slack","startX:" + startX + "," + pro + "," + max +"," + mwidth);
                        paint.setColor(progressSegmentColor);
                    }
                }else{
                    canvas.drawRect(startX, startY, ((float) progress / max) * mwidth,
                            mhight, paint);
                }



//                paint.setColor(Color.RED);
//                canvas.drawLine(startX, startY + (mhight - startY) / 4 * 2,
//                        ((float) progress / max) * mwidth, startY + (mhight - startY)
//                                / 4 * 2, paint);

                paint.setStrokeWidth(1);//
                paint.setColor(progressDoubleSegColor);

                if(progressList.size() > 0){
                    for(int i = 0;i<progressList.size() -1;i++){
                        canvas.drawLine(((float) progressList.get(i) / max) * mwidth,startY,((float) progressList.get(i) / max) * mwidth, startY + (mhight - startY),paint);
                    }
                }
                if(showText){

                    if(progress<(max/3)){
                        paint.setColor(textLowColor);
                    }else if(progress<(max/3)*2&&progress>(max/3)){
                        paint.setColor(textMiddleColor);
                    }else{
                        paint.setColor(textHighColor);
                    }

                    canvas.drawText(progress + "%", ((float) progress / max) * mwidth - (progress == 0 ? 0 : textSize),
                            mhight + textSize, paint);
                }
                break;
            case 1:
                paint.setStyle(Paint.Style.STROKE);
                paint.setColor(proColor);
                circleRectf.set(circleX,circleX,circleX + circleR * 2,circleX + circleR * 2);
                if(progressList.size() > 0){
                    startR = -90;
                    float last = 0;
                    boolean isOu = true;
                    for(int pro : progressList){

                        canvas.drawArc(circleRectf, startR, ((pro-last) / max) * 360 ,false, paint);
                        startR = ((pro-last) / max) * 360 + startR;
                        last = pro;
//                        Log.i("slack","startR:" + startR);
                        if(isOu){
                            paint.setColor(progressSegmentColor);
                        }else {
                            paint.setColor(proColor);
                        }
                        isOu = !isOu;
                    }
                }else{
                    canvas.drawArc(circleRectf, startR, ((float) progress / max) * 360, false, paint);
                }



                if(showText){
                    paint.reset();
                    paint.setStrokeWidth(1);
                    paint.setTextSize(textSize);
                    if(progress<(max/3)){
                        paint.setColor(textLowColor);
                    }else if(progress<(max/3)*2&&progress>(max/3)){
                        paint.setColor(textMiddleColor);
                    }else{
                        paint.setColor(textHighColor);
                    }
                    if (progress == max) {
                        canvas.drawText("done", circleX + textSize/2f ,circleX + textSize *2f  , paint);
                    } else {
                        canvas.drawText(progress + "%", circleX + textSize/2f  ,circleX + textSize*2f , paint);
                    }
                }
                break;
            case 2:
                squareRectf.set(startX, startY, mwidth, mhight);
                canvas.drawRoundRect(squareRectf,squareRadius,squareRadius,paint);
                paint.setColor(proColor);
                if(progressList.size() > 0){
                    for(int pro : progressList){
                        squareRectf.set(startX, startY, ((float) pro / max) * mwidth,mhight);
                        canvas.drawRoundRect(squareRectf,squareRadius,squareRadius,paint);
                        startX = ((float) pro/max) * mwidth;
//                        Log.i("slack","startX:" + startX + "," + pro + "," + max +"," + mwidth);
                        paint.setColor(progressSegmentColor);
                    }
                }else{
                    squareRectf.set(startX, startY, ((float) progress / max) * mwidth,mhight);
                    canvas.drawRoundRect(squareRectf,squareRadius,squareRadius,paint);
                }

                paint.setColor(progressDoubleSegColor);
                paint.setStrokeWidth(1);
                if(progressList.size() > 0){
                    for(int i = 0;i<progressList.size() -1;i++){

                        canvas.drawLine(((float) progressList.get(i) / max) * mwidth,startY,((float) progressList.get(i) / max) * mwidth, startY + (mhight - startY),paint);
                    }
                }
                if(showText){
                    if(progress<(max/3)){
                        paint.setColor(textLowColor);
                    }else if(progress<(max/3)*2&&progress>(max/3)){
                        paint.setColor(textMiddleColor);
                    }else{
                        paint.setColor(textHighColor);
                    }
                    canvas.drawText(progress + "%", ((float) progress / max) * mwidth - (progress == 0 ? 0 : textSize),
                            mhight + textSize, paint);
                }

                break;
            default:break;
        }



    }


    // - - - - - - - - - - - - -  public - - - - - - - - - - - - - - - - -


    public int getProgress() {
        return progress;
    }

    public void setProgress(int progress) {
        setProgress(progress,false);
    }

    public void setProgress(int progress,boolean needDel) {
        if(progress <= max){
            this.progress = progress;
            if(needDel){
                progressList.add(progress);
            }
            invalidate();
        }
    }
    public void removeProgress(int progres) {
        if(progressList.size() > 0){
            progressList.remove(progressList.size() - 1 );
            if(progressList.size() == 0){
                progress = DEFAULT_PROGRESS;
            }else {
                progress = progressList.get(progressList.size() - 1);
            }
        }else{
            progress = progres;
        }
        invalidate();
    }


}

主要工作都在onDraw裡完成,就是各種繪製嘛,東西不難,主要記錄一個過程


- - - - - - - - - - - - 更新 增加倒計時功能  - - - - - - - - - - - - - - - - - - - - - -

功能與這個一樣,看看效果,專案地址不變