安卓 节点进度条NodeProgressBar

安卓节点进度NodeProgressBar条如图:

 NodeProgressView.class 文件代码

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


public class NodeProgressView extends View {
    private Paint bgPaint;
    private Paint proPaint;
    private float bgRadius;
    private float proRadius;
    private float startX;
    private float stopX;
    private float bgCenterY;
    private int lineBgWidth;
    private int bgColor;
    private int lineProWidth;
    private int proColor;
    private int textColor;
    private int textPadding;
    private int maxStep;
    private int textSize;
    private int proStep;
    private float interval;
    private Integer[] nodes = new Integer[]{0, 5, 8, 15, 20};
    private String[] titles = {"累计", "5", "8", "15", "20"};

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

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

    public NodeProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ProgressViewH);
        bgRadius = ta.getDimension(R.styleable.ProgressViewH_h_bg_radius, 10);
        proRadius = ta.getDimension(R.styleable.ProgressViewH_h_pro_radius, 8);
        lineBgWidth = (int) ta.getDimension(R.styleable.ProgressViewH_h_bg_width, 3f);
        bgColor = ta.getColor(R.styleable.ProgressViewH_h_bg_color, Color.parseColor("#CCCCCC"));
        lineProWidth = (int) ta.getDimension(R.styleable.ProgressViewH_h_pro_width, 2f);
        proColor = ta.getColor(R.styleable.ProgressViewH_h_pro_color, Color.parseColor("#029dd5"));
        textPadding = (int) ta.getDimension(R.styleable.ProgressViewH_h_text_padding, 30);
        maxStep = ta.getInt(R.styleable.ProgressViewH_h_max_step, 5);
        textSize = (int) ta.getDimension(R.styleable.ProgressViewH_h_text_size, 20);
        textColor = ta.getColor(R.styleable.ProgressViewH_h_text_color, Color.parseColor("#272718"));
        proStep = ta.getInt(R.styleable.ProgressViewH_h_pro_step, 1);
        ta.recycle();
        init();
    }

    private void init() {
        bgPaint = new Paint();
        bgPaint.setAntiAlias(true);
        bgPaint.setStyle(Paint.Style.FILL);
        bgPaint.setColor(bgColor);
        bgPaint.setStrokeWidth(lineBgWidth);
        bgPaint.setTextSize(textSize);
        bgPaint.setTextAlign(Paint.Align.CENTER);

        proPaint = new Paint();
        proPaint.setAntiAlias(true);
        proPaint.setStyle(Paint.Style.FILL);
        proPaint.setColor(proColor);
        proPaint.setStrokeWidth(lineProWidth);
        proPaint.setTextSize(textSize);
        proPaint.setTextAlign(Paint.Align.CENTER);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        float bgWidth;
        if (widthMode == MeasureSpec.EXACTLY) {
            bgWidth = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
        } else {
            bgWidth = dip2px(getContext(), 311);
        }

        float bgHeight;
        if (heightMode == MeasureSpec.EXACTLY) {
            bgHeight = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
        } else {
            bgHeight = dip2px(getContext(), 49);
        }
        float left = getPaddingLeft() + bgRadius;
        stopX = bgWidth - bgRadius;
        startX = left;
        bgCenterY = bgHeight / 2;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        interval = ((stopX - startX) / (float) maxStep);
        drawBg(canvas);
        drawProgress(canvas);
        drawText(canvas);
    }

    private void drawText(Canvas canvas) {
        int index = 0;
        bgPaint.setColor(textColor);
        for (int i = 0; i <= maxStep; i++) {
            if (isContains(i)) {
                if (null != titles && index < titles.length) {
                    String title = titles[index++];
                    if (null == title) {
                        continue;
                    }
                    canvas.drawText(title, startX + (i * interval), bgCenterY + textPadding, bgPaint);
                }
            }
        }
    }

    private boolean isContains(int i) {
        boolean status = false;
        for (int value : nodes) {
            if (value == i) {
                status = true;
                break;
            }
        }
        return status || i == maxStep;
    }


    private void drawProgress(Canvas canvas) {
        float lastLeft = startX;
        if (proStep > maxStep) {
            proStep = maxStep;
        }
        canvas.drawLine(lastLeft, bgCenterY, lastLeft + interval * proStep, bgCenterY, proPaint);
        for (int i = 0; i <= proStep; i++) {
            if (isContains(i) && proStep != 0) {
                lastLeft = lastLeft + interval;
                canvas.drawCircle(startX + (i * interval), bgCenterY, proRadius, proPaint);
            }
        }
    }

    private void drawBg(Canvas canvas) {
        bgPaint.setColor(bgColor);
        canvas.drawLine(startX, bgCenterY, stopX, bgCenterY, bgPaint);
        for (int i = 0; i <= maxStep; i++) {
            if (isContains(i)) {
                canvas.drawCircle(startX + (i * interval), bgCenterY, bgRadius, bgPaint);
            }
        }
    }

    /**
     * 进度设置
     *
     * @param progress 已完成到哪部
     * @param maxStep  总步骤
     * @param nodes    需要显示对应节
     * @param titles   步骤名称
     */
    public void initProgress(int progress, int maxStep, Integer[] nodes, String[] titles) {
        proStep = progress;
        this.maxStep = maxStep;
        this.nodes = nodes;
        this.titles = titles;
        invalidate();
    }

    /**
     * 进度设置
     *
     * @param progress 已完成到哪部
     */
    public void setProgress(int progress) {
        proStep = progress;
        invalidate();
    }

    /**
     * 把密度转换为像素
     */
    private int dip2px(Context context, float px) {
        final float scale = getScreenDensity(context);
        return (int) (px * scale + 0.5);
    }

    /**
     * 得到设备的密度
     */
    private float getScreenDensity(Context context) {
        return context.getResources().getDisplayMetrics().density;
    }
}

 attrs.xml 文件代码

   <declare-styleable name="ProgressViewH">
        <attr name="h_bg_radius" format="dimension" />
        <attr name="h_pro_radius" format="dimension" />
        <attr name="h_bg_width" format="dimension" />
        <attr name="h_bg_color" format="color" />
        <attr name="h_pro_width" format="dimension" />
        <attr name="h_pro_color" format="color" />
        <attr name="h_text_padding" format="dimension" />
        <attr name="h_max_step" format="integer" />
        <attr name="h_text_size" format="dimension" />
        <attr name="h_text_color" format="color" />
        <!--总进度-->
        <attr name="h_pro_step" format="integer" />
    </declare-styleable>

控件用法

   <NodeProgressView
        android:id="@+id/progress"
        android:layout_width="match_parent"
        android:layout_height="113dp"
        android:paddingStart="20dp"
        app:h_bg_color="#A4A6A8"
        app:h_bg_radius="8dp"
        app:h_bg_width="10dp"
        app:h_max_step="20"
        app:h_pro_color="#48B46C"
        app:h_pro_radius='8dp'
        app:h_pro_step="8"
        app:h_pro_width="10dp"
        app:h_text_padding="20dp"
        app:h_text_size="12sp"/>


/**
* 进度设置
*
* @param progress 已完成到哪一步
* @param maxStep 总步骤
* @param nodes 需要显示对应节
* @param titles 步骤名称
*/
viewBinding.progress.initProgress(bean.clockNum, bean.daysList[bean.daysList.size - 1], bean.daysList.toTypedArray(), titles.toTypedArray())
原文地址:https://www.cnblogs.com/blogzhangwei/p/14526671.html