設計思路:
1.畫柱狀圖
2.畫豎線
3.畫頂部橫線
4.畫文字
1.畫柱狀圖
畫柱狀圖的方法很簡單,就是使用canvas.drawRect(float left, float top, float right, float bottom, Paint paint),其實這裏我遇到了一個問題,一開始我想只畫一條柱狀圖,然後需要幾個柱狀圖就在xml文件中聲明幾個,後來我發現,這樣實現起來的動畫非常之卡頓(上面gif錄出來看上去很卡,其實很流暢)。後來我就換了一種思路,就是聲明一個數組,在Activity傳入我們需要畫的柱狀圖的總個數和每個柱狀圖的目標值大小,然後在onDraw方法裏分別計算每個柱狀圖的當前進度,然後分別畫出來,這樣動畫效果就非常流暢了。
/**
* 畫柱狀圖
*/
for(int i = 0 ; i<totalBarNum ; i++){
if (currentBarProgress[i]<(respTarget.get(i)/max)*stopX) {
currentBarProgress[i]+=10;
postInvalidateDelayed(10);
}
canvas.drawText(respName.get(i),startX,startY+deltaY+i*(deltaY+barWidth)+3*barWidth/4, mTextPaint);
canvas.drawRect(startX+7*barWidth/5, startY+deltaY+i*(deltaY+barWidth), currentBarProgress[i], startY+deltaY+i*(deltaY+barWidth)+barWidth, mBarPaint);
}
2.畫豎線和文字
有了上面畫柱狀圖的思路,畫豎線就非常容易想了,和畫柱狀圖是一個思路,也是Activity中傳入需要畫幾條豎線,然後在onDraw方法裏分別去計算他們的當前進度值,然後再分別去畫
文字大小應該隨着柱形圖寬度來自動適應,所以我進行了一些計算,看上去很複雜,其實就是爲了自適應文字的大小
/**
* 畫豎線
*/
for(int i=0 ; i<verticalLineNum ; i++){
if (currentVerticalLineProgress< measuredHeight) {
currentVerticalLineProgress+=3;
postInvalidateDelayed(10);
}
canvas.drawLine((startX+7*barWidth/5)+(i+1)*deltaX, startY, (startX+7*barWidth/5)+(i+1)*deltaX, currentVerticalLineProgress, mLinePaint);
//畫文字
canvas.drawText(numPerUnit*(i+1)+unit, (startX+7*barWidth/5)+(i+1)*deltaX-barWidth, startY-barWidth/5, mTextPaint);
}
3.畫頂部橫線
頂部橫線我是從右向左畫的,正好與柱狀圖形成一個對比
/**
* 畫最上面的橫線
*/
if (currentHorizentalLineProgress>startX+7*barWidth/5) {
currentHorizentalLineProgress-=10;
postInvalidateDelayed(10);
}
canvas.drawLine(stopX, startY, currentHorizentalLineProgress, startY, mLinePaint);
}
使用方法
1.設置柱狀圖的最大值
mBarGraph.setMax(40);
2.設置柱狀圖單位
mBarGraph.setUnit("億元");
3.設置柱狀圖寬度
mBarGraph.setBarWidth(50);
4.設置豎線條數
mBarGraph.setVerticalLineNum(4);
5.設置柱狀圖總個數
mBarGraph.setTotalBarNum(7);
6.設置每個柱狀圖的目標值
private ArrayList<Float> respectTarget;
...
respectTarget = new ArrayList<Float>();
respectTarget.add(35.0f);
respectTarget.add(20.0f);
respectTarget.add(18.0f);
respectTarget.add(15.0f);
respectTarget.add(10.0f);
respectTarget.add(8.0f);
respectTarget.add(5.0f);
mBarGraph.setRespectTargetNum(respectTarget);
7.設置每個柱狀圖的名字
private ArrayList<String> respName;
...
respName = new ArrayList<String>();
respName.add("滴滴");
respName.add("小米");
respName.add("京東");
respName.add("美團");
respName.add("魅族");
respName.add("酷派");
respName.add("攜程");
mBarGraph.setRespectName(respName);
完整代碼
大家可以上我的GitHub上下載完整代碼