Android中水平結點進度條StepHorizontalView

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

二 、使用方式

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

三、佈局

<com.example.zyt.mystepview.mine.StepHorizontalView
        android:id="@+id/sv_step"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:background="@android:color/darker_gray"
        app:h_bg_color="@color/colorPrimaryDark"
        app:h_bg_radius="6dp"
        app:h_bg_width="4dp"
        app:h_pro_color="@android:color/holo_red_light"
        app:h_pro_radius="6dp"
        app:h_pro_width="5dp"
        app:h_max_step="5"
        app:h_pro_step="2"
        app:h_text_padding="30dp"
        app:h_textsize="16sp" />

四、屬性講解

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<String> titles;
    private Map<String, Integer> 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<String> titles){
        this.titles = titles;
    }
}

六、在values中創建一個attrs.xml文件

    <!--step view -->
    <declare-styleable name="FlowViewHorizontal">
        <attr name="h_bg_radius" format="dimension" />
        <attr name="h_pro_radius" format="dimension" />
        <attr name="h_bg_width" format="dimension" />
        <attr name="h_pro_width" format="dimension" />
        <attr name="h_bg_color" format="color" />
        <attr name="h_pro_color" format="color" />
        <attr name="h_text_padding" format="dimension" />
        <attr name="h_max_step" format="integer" />
        <attr name="h_textsize" format="dimension" />
        <attr name="h_pro_step" format="integer" />
    </declare-styleable>

七、不足之處

這個控件不能wrap_content,但不會報錯,只是效果和match_parent一樣,所以儘量寫明具體高度。

若有問題,請大家多多指正。


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