自定义绘制柱形图详解手机开发

这里写图片描述

设计思路:

1.画柱状图 
2.画竖线 
3.画顶部横线 
4.画文字

1.画柱状图

画柱状图的方法很简单,就是使用canvas.drawRect(float left, float top, float right, float bottom, Paint paint),其实这里我遇到了一个问题,一开始我想只画一条柱状图,然后需要几个柱状图就在xml文件中声明几个,后来我发现,这样实现起来的动画非常之卡顿(上面gif录出来看上去很卡,其实很流畅)。后来我就换了一种思路,就是声明一个数组,在Activity传入我们需要画的柱状图的总个数和每个柱状图的目标值大小,然后在onDraw方法里分别计算每个柱状图的当前进度,然后分别画出来,这样动画效果就非常流畅了。

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** 
         * 画柱状图 
         */ 
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0 ; i<totalBarNum ; i++){ 
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if (currentBarProgress[i]<(respTarget.get(i)/max)*stopX) { 
                currentBarProgress[i]+=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10; 
                postInvalidateDelayed(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10); 
            } 
            canvas.drawText(respName.get(i),startX,startY+deltaY+i*(deltaY+barWidth)+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3*barWidth/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4, mTextPaint); 
            canvas.drawRect(startX+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7*barWidth/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5, startY+deltaY+i*(deltaY+barWidth), currentBarProgress[i], startY+deltaY+i*(deltaY+barWidth)+barWidth, mBarPaint); 
        }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

2.画竖线和文字

有了上面画柱状图的思路,画竖线就非常容易想了,和画柱状图是一个思路,也是Activity中传入需要画几条竖线,然后在onDraw方法里分别去计算他们的当前进度值,然后再分别去画

文字大小应该随着柱形图宽度来自动适应,所以我进行了一些计算,看上去很复杂,其实就是为了自适应文字的大小

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** 
         * 画竖线 
         */ 
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0 ; i<verticalLineNum ; i++){ 
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if (currentVerticalLineProgress< measuredHeight) { 
                currentVerticalLineProgress+=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3; 
                postInvalidateDelayed(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10); 
            } 
            canvas.drawLine((startX+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7*barWidth/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5)+(i+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1)*deltaX, startY, (startX+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7*barWidth/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5)+(i+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1)*deltaX, currentVerticalLineProgress, mLinePaint); 
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//画文字 
            canvas.drawText(numPerUnit*(i+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1)+unit, (startX+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7*barWidth/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5)+(i+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1)*deltaX-barWidth, startY-barWidth/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5, mTextPaint); 
        }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>

3.画顶部横线

顶部横线我是从右向左画的,正好与柱状图形成一个对比

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** 
         * 画最上面的横线 
         */ 
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if (currentHorizentalLineProgress>startX+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7*barWidth/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5) { 
            currentHorizentalLineProgress-=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10; 
            postInvalidateDelayed(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10); 
        } 
        canvas.drawLine(stopX, startY, currentHorizentalLineProgress, startY, mLinePaint); 
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

使用方法

1.设置柱状图的最大值

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">mBarGraph<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setMax(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">40)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

2.设置柱状图单位

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">mBarGraph<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setUnit(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"亿元")<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

3.设置柱状图宽度

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">mBarGraph<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setBarWidth(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">50)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

4.设置竖线条数

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">mBarGraph<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setVerticalLineNum(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

5.设置柱状图总个数

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> mBarGraph<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setTotalBarNum(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

6.设置每个柱状图的目标值

<code class="hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> private ArrayList<Float> respectTarget; 
 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">... 
 respectTarget = new ArrayList<Float>(); 
 respectTarget.add(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">35.0f); 
        respectTarget.add(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20.0f); 
        respectTarget.add(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18.0f); 
        respectTarget.add(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">15.0f); 
        respectTarget.add(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10.0f); 
        respectTarget.add(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8.0f); 
        respectTarget.add(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5.0f); 
  mBarGraph.setRespectTargetNum(respectTarget);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

7.设置每个柱状图的名字

<code class="hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">private ArrayList<String> respName; 
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">... 
respName = new ArrayList<String>(); 
 respName.add(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"滴滴"); 
        respName.add(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"小米"); 
        respName.add(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"京东"); 
        respName.add(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"美团"); 
        respName.add(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"魅族"); 
        respName.add(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"酷派"); 
        respName.add(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"携程"); 
mBarGraph.setRespectName(respName);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

完整代码

大家可以上我的GitHub上下载完整代码

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/5673.html

(0)
上一篇 2021年7月17日
下一篇 2021年7月17日

相关推荐

发表回复

登录后才能评论