自定义View之线性进度展示

目前有很多APP都具有进度展示功能,而进度展示的效果多种多样,0.0就要看你们UI坑不坑了,有简单的,也有复杂的,首先分析一下UI图,

UI.png

本来想着用多个view组合完成的,但想想自定义view逼格高对性能也好,所以就用自定义view吧。先上波demo图:

XIAN.gif

思路

根据分类的个数n ,开始画圆和上部分标题,线的个数 =分类的个数-1,主要的还是先计算出每个圆心的坐标,先画线然后画圆,这样就可以让圆把线盖住一部分实现效果,而不用在计算两个圆之间的距离再画线了, 而圆心的坐标我们根据输入的width把分成 width/n 分就好,width/n / 2 就为第一个圆的x坐标,然后类推,下方内容矩形,是先画一个矩形,然后在上方画一个三角形,然后在矩形中间开始画text,具体实现请看代码。

代码

public class MyScheduleView extends View {
    private  Context mcontext;
    //进度个数
    private int ScheduleCount = 3;
    // 圆的颜色
    private int circleColor;
    // 线的颜色
    private int lineColor = Color.BLACK;
   // 当前进度
    private  int progress = 1;

    /* 测量文本宽高的矩形 */
    private Rect mTextRect;

    /* 测量title文本宽高的矩形 */
    private Rect tTextRect;

    //用来内容文本的矩形
    private Rect cTextRect;


   private  String  texttitle [] ={"天使投资人","至尊VIP","黑金VIP","联合创始人"};
    // 标签text 画笔
    private Paint ttPaint;

    /* 文本画笔 */
    private Paint mTextPaint;
    // 三角形画笔
    private Paint tipPaint;
  //  文本大小
    private float textsize ;
    //  标签文本大小
    private float ttextsize ;


 // 矩形画笔
    private Paint RECpaint;
  // 矩形
    private RectF recRect= new RectF();
    /**
     * 画三角形的path
     */
    private Path path = new Path();
    /**
     * 三角形的高
     */
    private int triangleHeight;
    /*
     * view的高度
     */
    private int height;
    private int width;
    // 圆的半径
    private float circlewidth= 10;
    //线的高度
    private float linehight = 10;
    /* 线画笔 */
    private Paint mLinePaint;
    /* 圆画笔 */
    private Paint CirclePaint;
    /**
     * 第一个圆开始绘制的圆心坐标
     */
    private float startX;
    private float startY;

    private String  textcont[] ={"累计年化投资额达10万,邀约3人以上,即晋级为天使投资人","累计年化投资额达30万,邀约3人以上,即晋级为至尊VIP","累计年化投资额达60万,邀约3人以上,即晋级为黑金VIP","累计年化投资额达90万,邀约3人以上,即晋级为联合创始人","通关。。。。。。。。。。。。。。。。。。"};

    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();
    }
    /**
     * 初始化画笔
     */
    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);
    }

    /**
     * 设置画笔
     * @param style       画笔风格
     * @param color       画笔颜色
     * @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);
        }
    }

    /**
     * 画实心圆
     *
     * @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);
        }
    }
    // 画线
    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);
        }
    }
  // 绘制内容文本
    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>

注意

由于 画下方矩形的起始位置是固定的,画其宽度时,根据的是text文本的宽度,所以当字符串的长度太小而进度很高时,不适用,可以在画矩形时,给矩形设置固定宽度就可以了。

项目地址:
csdn:http://download.csdn.net/download/qq_38367802/10172775
github:https://github.com/liuzhenhang/myview

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容