自定義View之線性進(jìn)度展示

目前有很多APP都具有進(jìn)度展示功能,而進(jìn)度展示的效果多種多樣,0.0就要看你們UI坑不坑了,有簡(jiǎn)單的,也有復(fù)雜的,首先分析一下UI圖,

UI.png

本來(lái)想著用多個(gè)view組合完成的,但想想自定義view逼格高對(duì)性能也好,所以就用自定義view吧。先上波demo圖:

XIAN.gif

思路

根據(jù)分類的個(gè)數(shù)n ,開(kāi)始畫(huà)圓和上部分標(biāo)題,線的個(gè)數(shù) =分類的個(gè)數(shù)-1,主要的還是先計(jì)算出每個(gè)圓心的坐標(biāo),先畫(huà)線然后畫(huà)圓,這樣就可以讓圓把線蓋住一部分實(shí)現(xiàn)效果,而不用在計(jì)算兩個(gè)圓之間的距離再畫(huà)線了, 而圓心的坐標(biāo)我們根據(jù)輸入的width把分成 width/n 分就好,width/n / 2 就為第一個(gè)圓的x坐標(biāo),然后類推,下方內(nèi)容矩形,是先畫(huà)一個(gè)矩形,然后在上方畫(huà)一個(gè)三角形,然后在矩形中間開(kāi)始畫(huà)text,具體實(shí)現(xiàn)請(qǐng)看代碼。

代碼

public class MyScheduleView extends View {
    private  Context mcontext;
    //進(jìn)度個(gè)數(shù)
    private int ScheduleCount = 3;
    // 圓的顏色
    private int circleColor;
    // 線的顏色
    private int lineColor = Color.BLACK;
   // 當(dāng)前進(jìn)度
    private  int progress = 1;

    /* 測(cè)量文本寬高的矩形 */
    private Rect mTextRect;

    /* 測(cè)量title文本寬高的矩形 */
    private Rect tTextRect;

    //用來(lái)內(nèi)容文本的矩形
    private Rect cTextRect;


   private  String  texttitle [] ={"天使投資人","至尊VIP","黑金VIP","聯(lián)合創(chuàng)始人"};
    // 標(biāo)簽text 畫(huà)筆
    private Paint ttPaint;

    /* 文本畫(huà)筆 */
    private Paint mTextPaint;
    // 三角形畫(huà)筆
    private Paint tipPaint;
  //  文本大小
    private float textsize ;
    //  標(biāo)簽文本大小
    private float ttextsize ;


 // 矩形畫(huà)筆
    private Paint RECpaint;
  // 矩形
    private RectF recRect= new RectF();
    /**
     * 畫(huà)三角形的path
     */
    private Path path = new Path();
    /**
     * 三角形的高
     */
    private int triangleHeight;
    /*
     * view的高度
     */
    private int height;
    private int width;
    // 圓的半徑
    private float circlewidth= 10;
    //線的高度
    private float linehight = 10;
    /* 線畫(huà)筆 */
    private Paint mLinePaint;
    /* 圓畫(huà)筆 */
    private Paint CirclePaint;
    /**
     * 第一個(gè)圓開(kāi)始繪制的圓心坐標(biāo)
     */
    private float startX;
    private float startY;

    private String  textcont[] ={"累計(jì)年化投資額達(dá)10萬(wàn),邀約3人以上,即晉級(jí)為天使投資人","累計(jì)年化投資額達(dá)30萬(wàn),邀約3人以上,即晉級(jí)為至尊VIP","累計(jì)年化投資額達(dá)60萬(wàn),邀約3人以上,即晉級(jí)為黑金VIP","累計(jì)年化投資額達(dá)90萬(wàn),邀約3人以上,即晉級(jí)為聯(lián)合創(chuàng)始人","通關(guān)。。。。。。。。。。。。。。。。。。"};

    public MyScheduleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mcontext = context;
        getAtt(attrs);
        initPaint();
    }
    private void getAtt(AttributeSet attrs) {
        TypedArray typedArray = mcontext.obtainStyledAttributes(attrs, R.styleable.MyScheduleView);
        ScheduleCount = typedArray.getInt(R.styleable.MyScheduleView_ScheduleCount, ScheduleCount);
        circleColor = typedArray.getColor(R.styleable.MyScheduleView_scircleColor,  Color.parseColor("#df0781"));
        lineColor =typedArray.getColor(R.styleable.MyScheduleView_lineColor, lineColor);
        circlewidth = typedArray.getDimension(R.styleable.MyScheduleView_circleWidth,dp2px(10));
        linehight = typedArray.getDimension(R.styleable.MyScheduleView_linehight,linehight);
        textsize = typedArray.getDimension(R.styleable.MyScheduleView_msvTextsize,textsize);
        ttextsize = typedArray.getDimension(R.styleable.MyScheduleView_msvTTextsize,ttextsize);
        typedArray.recycle();
        mTextRect = new Rect();
        tTextRect = new Rect();
        cTextRect = new Rect();
    }
    /**
     * 初始化畫(huà)筆
     */
    private void initPaint() {
        mLinePaint = new Paint();
        mLinePaint.setStyle(Paint.Style.FILL);
        mLinePaint.setColor(circleColor);
        mLinePaint.setAntiAlias(true);

        ttPaint = new Paint();
        ttPaint.setStyle(Paint.Style.FILL);
        ttPaint.setColor(Color.BLACK);
        ttPaint.setTextSize(ttextsize);
        ttPaint.setAntiAlias(true);

        CirclePaint = new Paint();
        CirclePaint.setStyle(Paint.Style.FILL);
        CirclePaint.setColor(circleColor);
        CirclePaint.setAntiAlias(true);

        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setStyle(Paint.Style.FILL);
        mTextPaint.setColor(Color.WHITE);
        mTextPaint.setTextSize(textsize);
        mTextPaint.setAntiAlias(true);

        RECpaint = new Paint();
        RECpaint.setStyle(Paint.Style.FILL);
        RECpaint.setColor(Color.BLUE);
        CirclePaint.setAntiAlias(true);

        tipPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        tipPaint.setColor(Color.BLUE);
        tipPaint.setAntiAlias(true);
        tipPaint.setStrokeCap(Paint.Cap.ROUND);
        tipPaint.setStyle(Paint.Style.FILL);
    }

    /**
     * 設(shè)置畫(huà)筆
     * @param style       畫(huà)筆風(fēng)格
     * @param color       畫(huà)筆顏色
     * @return
     */
    private Paint getPaint( Paint.Style style, int color) {
        Paint paint = new Paint(ANTI_ALIAS_FLAG);
        paint.setStyle(style);
        paint.setColor(color);
        paint.setAntiAlias(true);
        return paint;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
        startX = w / ScheduleCount / 2;
        startY = h / 2;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawLine(canvas);
        drawCircle(canvas);
        drawTriangle(canvas);
        drawText(canvas);
        drawTitle(canvas);
    }

    private void drawTitle(Canvas canvas) {
        for (int i = 0; i < ScheduleCount; i++) {
            if (i<=progress-1){
                ttPaint.setColor(circleColor);
            }else {
                ttPaint.setColor(Color.BLACK);;
            }
          //  canvas.drawCircle(startX + i * 2 * startX, startY, circlewidth, CirclePaint);
            ttPaint.getTextBounds(texttitle[i], 0, texttitle[i].length(), tTextRect);
            float TextWidth = tTextRect.width();
            float TextHeight = tTextRect.height();
            canvas.drawText(texttitle[i],startX + i * 2 * startX-TextWidth/2, (float) (getHeight()/ 2 - TextHeight), ttPaint);
        }
    }

    /**
     * 畫(huà)實(shí)心圓
     *
     * @param canvas
     */
    private void drawCircle(Canvas canvas) {
        for (int i = 0; i < ScheduleCount; i++) {
          if (i<=progress-1){
              CirclePaint.setColor(circleColor);
          }else {
              CirclePaint.setColor(Color.BLACK);;
          }
            canvas.drawCircle(startX + i * 2 * startX, startY, circlewidth, CirclePaint);
        }
    }
    // 畫(huà)線
    private void drawLine(Canvas canvas) {
        for (int i = 0; i < ScheduleCount-1; i++) {
            if (i<=progress-2){
                mLinePaint.setColor(lineColor);
            }else {
                mLinePaint.setColor(Color.BLACK);;
            }
            canvas.drawLine(startX + i * 2 * startX,height/2,startX + (i+1) * 2 * startX,height/2,mLinePaint);
        }
    }
  // 繪制內(nèi)容文本
    private void drawText(Canvas canvas) {
        mTextPaint.getTextBounds(textcont[progress], 0, textcont[progress].length(), mTextRect);
        float TextWidth = mTextRect.width();
        float TextHeight = mTextRect.height();
        cTextRect.set((int)(startX - (2 * circlewidth)),(int)((height / 2) + 2 * circlewidth),(int)(startX+TextWidth ), (int)((height / 2) + (5 * circlewidth)));
        // 繪制矩形
      canvas.drawRect(cTextRect, RECpaint);

        Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
        // 獲取baseLine
        int baseline = cTextRect.top + (cTextRect.bottom - cTextRect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText(textcont[progress],cTextRect.centerX(),baseline, mTextPaint);

    }


    /**
     * 繪制三角形
     *
     * @param canvas
     */
    private void drawTriangle(Canvas canvas) {
        for (int i = 0; i < ScheduleCount; i++) {
            if (i == progress-1){
                path.moveTo(startX + i * 2 * startX, (float) (height / 2+1.5*circlewidth));
                path.lineTo((float) (startX + i * 2 * startX-0.5*circlewidth),  height / 2+2*circlewidth);
                path.lineTo((float) (startX + i * 2 * startX+0.5*circlewidth), height / 2+2*circlewidth);
                canvas.drawPath(path, tipPaint);
                path.reset();
            }
        }
    }

    public void setProgress(int mprogress) {
        progress = mprogress;
        invalidate();
    }


    /**
     * dp 2 px
     *
     * @param dpVal
     */
    protected int dp2px(int dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, getResources().getDisplayMetrics());
    }
}
    

attr 文件

<declare-styleable name="MyScheduleView">
        <attr name="circleWidth" format="dimension" />
        <attr name="ScheduleCount" format="integer" />
        <attr name="lineWidth" format="dimension" />
        <attr name="linehight" format="dimension" />
        <attr name="scircleColor" format="color" />
        <attr name="lineColor" format="color" />
        <attr name="msvTextsize" format="dimension"></attr>
        <attr name="msvTTextsize" format="dimension"></attr>
    </declare-styleable>

注意

由于 畫(huà)下方矩形的起始位置是固定的,畫(huà)其寬度時(shí),根據(jù)的是text文本的寬度,所以當(dāng)字符串的長(zhǎng)度太小而進(jìn)度很高時(shí),不適用,可以在畫(huà)矩形時(shí),給矩形設(shè)置固定寬度就可以了。

項(xiàng)目地址:
csdn:http://download.csdn.net/download/qq_38367802/10172775
github:https://github.com/liuzhenhang/myview

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容