Android中水平结点进度条StepHorizontalView

一、先看看效果,是不是你需要的

Android中水平结点进度条StepHorizontalView_第1张图片

二 、使用方式

        StepHorizontalView mStepSv = (StepHorizontalView) findViewById(R.id.sv_step);
        mStepSv.setProgress(3, 4);
        List list = new ArrayList<>();
        list.add("第一步");
        list.add("第二步");
        list.add("第三步");
        list.add("第四步");
        mStepSv.setTitles(list);

三、布局

四、属性讲解

1. h_bg_color                 默认进度条的颜色

2. h_bg_radius               默认节点的半径大小

3. h_bg_width                 默认间隔线的宽度

4. h_pro_color                已过进度条的颜色

5. h_pro_radius              已过节点的半径大小

6. h_pro_width               已过间隔线的宽度

7. h_text_padding          进度条与文本的距离

8. h_textsize                  文本的字体大小

9. h_max_step               最多节点的个数

10. h_pro_step              节点的进度

五、自定义控件

public class StepHorizontalView extends View {

    private int bgWidth;
    private int bgHeight;
    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 textPadding;
    private int maxStep;
    private int textSize;
    private int proStep;
    private Paint bgPaint;
    private Paint proPaint;
    private int interval;
    private List titles;
    private Map map;
    private float startLine;
    private float stopLine;

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

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

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

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.FlowViewHorizontal);
        bgRadius = ta.getDimension(R.styleable.FlowViewHorizontal_h_bg_radius, 10);
        proRadius = ta.getDimension(R.styleable.FlowViewHorizontal_h_pro_radius, 8);
        lineBgWidth = (int) ta.getDimension(R.styleable.FlowViewHorizontal_h_bg_width, 3f);
        bgColor = ta.getColor(R.styleable.FlowViewHorizontal_h_bg_color, Color.parseColor("#cccccc"));
        lineProWidth = (int) ta.getDimension(R.styleable.FlowViewHorizontal_h_pro_width, 2f);
        proColor = ta.getColor(R.styleable.FlowViewHorizontal_h_pro_color, Color.parseColor("#EF5350"));
        textPadding = (int) ta.getDimension(R.styleable.FlowViewHorizontal_h_text_padding, 20);
        maxStep = ta.getInt(R.styleable.FlowViewHorizontal_h_max_step, 6);
        textSize = (int) ta.getDimension(R.styleable.FlowViewHorizontal_h_textsize, 20);
        proStep = ta.getInt(R.styleable.FlowViewHorizontal_h_pro_step, 1);
        ta.recycle();
        initView();
    }

    private void initView() {
        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);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode == MeasureSpec.EXACTLY) {
            bgWidth = widthSize;
        } 

        if (heightMode == MeasureSpec.EXACTLY) {
            bgHeight = heightSize;
        }

        interval = (int) ((bgWidth-bgRadius*2-getPaddingRight()-getPaddingLeft())/(maxStep - 1));//紧挨着的两个圆心的距离
        startLine = getPaddingLeft() + bgRadius * 2;//作为线的起点
        stopLine = getPaddingLeft() + interval * (maxStep-1);//作为线的终点
        startX = getPaddingLeft() + bgRadius;//作为圆的起始点
        stopX = stopLine + bgRadius;//作为最后一个圆的圆心   bgWidth - bgRadius - getPaddingRight()
        bgCenterY = getPaddingTop()+bgRadius;//作为线和圆心的纵坐标
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawBg(canvas);
        drawProgress(canvas);
        drawText(canvas);
    }

    /**
     * 绘画文本
     * @param canvas
     */
    private void drawText(Canvas canvas) {
        for (int i = 0; i < maxStep; i++) {
            if (i < proStep) {
                if (null != titles && i < titles.size()) {
                    canvas.drawText(titles.get(i), startX + (i * interval), bgCenterY + textPadding + (bgRadius < proRadius ? proRadius : bgRadius), proPaint);
                }
            } else {
                if (null != titles && i < titles.size()) {
                    String title = titles.get(i);
                    if (null == title) {
                        continue;
                    }
                    canvas.drawText(title, startX + (i * interval), bgCenterY + textPadding + (bgRadius < proRadius ? proRadius : bgRadius), bgPaint);
                }
            }
        }
    }

    /**
     * 绘画底部默认进度条
     * @param canvas
     */
    private void drawBg(Canvas canvas) {
        canvas.drawLine(startLine, bgCenterY, stopLine, bgCenterY, bgPaint);
        for (int i = 0; i < maxStep; i++) {
            canvas.drawCircle(startX + (i * interval), bgCenterY, bgRadius, bgPaint);
        }
    }

    /**
     * 绘画进度
     * @param canvas
     */
    private void drawProgress(Canvas canvas) {
        for (int i = 0; i < proStep; i++) {
            canvas.drawCircle(startX + (i * interval), bgCenterY, proRadius, proPaint);

            canvas.drawLine(startX, bgCenterY, startX + (i * interval), bgCenterY, proPaint);
        }
    }

    /**
     * 进度设置
     *
     * @param progress 已完成到哪部
     * @param maxStep  总步骤
     */
    public void setProgress(int progress, int maxStep) {
        proStep = progress;
        this.maxStep = maxStep;
        invalidate();
    }

    public void setTitles(List titles){
        this.titles = titles;
    }
}

六、在values中创建一个attrs.xml文件

    
    
        
        
        
        
        
        
        
        
        
        
    

七、不足之处

这个控件不能wrap_content,但不会报错,只是效果和match_parent一样,所以尽量写明具体高度。

若有问题,请大家多多指正。

 

你可能感兴趣的:(自定义样式)