android條形圖繪製以及加入動畫,並且支援水平滑動
閒話
Android 圖表的繪製,無非是view的繪製,只有掌握了view的繪製流程,那麼一個條形圖,也沒有什麼可難繪製的,那為什麼會有人覺得比較難呢,其實是自己內心裡懼怕他,於是每次出現圖表需求,想都不用想就選擇第三方的,也就是別人寫好的,當然,這也沒有什麼,大家都會用的,也不只是你一個人在用,目前在github上star最多的可能就是MPAndroidChart了,做的的確很強大,但是再強大,有時候也會有那麼一丟丟的不符合我們自己的需求,這個時候,真是讓人哭笑不得啊,用的話,又不能達到產品的需求,不用吧,自己好像又沒有什麼思路,於是僵住了。
我花了點時間大致的看了下MPAndroidChart原始碼,的確內容很多,今天,就用自己的思想以及MPAndroidChart的思想相結合來寫一個比較簡單的條形圖,這樣也是對繪製view的一次學習吧
效果
- 不可滑動效果:
- 可滑動效果:
圖片看起來有點失真,還伴隨點卡頓,這是由於錄影是電腦和手機連線不穩定造成的,真實的動畫是不會有任何卡頓的。
理清思路
首先我們得理清思路,如何才能繪製出一個條形圖,不能連思路都沒有就去做,這樣真的很難下手。
1. 初始化操作
首先,圖表是自定義view,繼承自view,所以該重寫的方法都要重寫。
- 當圖表建立時,我們都需要準備什麼,第一個當然是畫筆Paint了,這個時候我們只需要對畫筆進行初始化,什麼顏色啊,填充方式啊等等。
- 除了初始化畫筆Paint外,我們還需要初始化的,就是動畫了,因為我們需要給條形圖加入動畫,這個時候,問題來了,動畫和條形圖如何結合起來?
- 能讓條形圖動起來的動畫當然是ValueAnimator或者ObjectAnimator了,這兩個動畫其實是一個東西,最終都是ValueAnimator,所以用哪個其實都可以實現,我用的是ObjectAnimator,因為MPAndroidChart也用的是ObjectAnimator。
- 究竟動畫怎麼才能和條形圖結合呢?
private void init() {
//初始化動畫
mAnimator = new ChartAnimator(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
postInvalidate();
}
});
mBound = new Rect();
//柱子畫筆
mChartPaint = new Paint();
mChartPaint.setAntiAlias(true);
mChartPaint.setColor(Color.parseColor(chartColor));
//線畫筆
linePaint = new Paint();
linePaint.setAntiAlias(true);
linePaint.setColor(Color.parseColor(lineColor));
//x縱座標 畫筆
textXpaint = new Paint();
textXpaint.setAntiAlias(true);
textXpaint.setTextSize(27f);
textXpaint.setTextAlign(Paint.Align.CENTER);
textXpaint.setColor(Color.parseColor(textColor));
//Y縱座標 畫筆
textYpaint = new Paint();
textYpaint.setAntiAlias(true);
textYpaint.setTextSize(28f);
textYpaint.setTextAlign(Paint.Align.LEFT);
textYpaint.setColor(Color.parseColor(textColor));
//無資料時的畫筆
noDataPaint = new Paint();
noDataPaint.setAntiAlias(true);
noDataPaint.setColor(Color.parseColor(noDataColor));
noDataPaint.setStyle(Paint.Style.FILL);
}
2. 動畫和條形圖的結合
大家都知道ValueAnimator動畫,是將兩個數經過計算之後,會得到一系列的數值,這些數值都會在這兩個值得區間,那麼這個時候,就能將生成的這些值和條形圖的高度聯絡到一起,ValueAnimator的值是從0到1的,生成的全是Float型別的值,可以理解為百分數,也就是從0%到100%,這個時候條形圖的動畫也就能實現了,每個條形圖的高度都從0開始繪製,一直繪製到他的真實高度,繪製完成後,動畫自然也就結束了,條形圖的高度佔這個view的高度的百分比,也就是佔整個圖表控制元件的高度的百分比是可以算出來的。
3. 測量高度
在onLayout方法裡,可以得到view的高度和寬度,因為我們需要在後面計算每個條形圖佔整個控制元件高度的百分比
在onLayout方法裡也需要計算條形圖的寬度和間隙,以及橫縱座標起始位置座標
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mWidth = getWidth();
mHeight = getHeight() - paddingTop;
chartWidth = mWidth - outSpace;
//每個柱子寬度
barWidth = (int) (chartWidth * barPercent);
interval = (int) (chartWidth * intevalPercent);
//所有柱子寬度 之和
allBarwidth = horizontalList.size() * barWidth;
//所有間隔寬 之和
allInteval = (horizontalList.size() - 1) * interval;
//所有柱子和間隔的寬度
allChartWidth = allBarwidth + allInteval;
//柱子開始的橫座標
startChart = outSpace + (chartWidth / 2f - allChartWidth / 2f);
//橫座標
textStart = startChart + (barWidth / 2f);
}
5. 開始繪製
- view的繪製全在onDraw方法裡,這個時候就用到onDraw方法中的canvas了,條形圖其實也就是矩形,所以也很好繪製,這個時候,我們需要了解的就是canvas的方法,他都能繪製些什麼,方法中的引數又是什麼意思並且代表著什麼,只有搞清楚了這些,我們才能正式開始下手繪製,否則,我們還是無從下手。
- canvas.drawRect(),這個方法其實才是我們重點要掌握的,他就是繪製矩形的方法,首先,你需要知道,他的引數的意義
- 他需要的引數為:(float left, float top, float right, float bottom,Paint paint ),乍一看,引數太多,看都不想看了,彆著急,他很簡單的,只不過就是座標而已,上下左右嘛,這有什麼難的,那麼這又分別代表著什麼呢,搞清楚這些我們才好下手呀。
- left表示矩形的左邊到view最左邊的距離,而不是螢幕的左邊,這個要搞清楚,top也就表示著矩形的上邊到view的頂部距離,而不是螢幕頂部,right是矩形的右邊到view的左邊距離,bottom是矩形的下邊到view的頂部的距離
- 只要你搞清楚了上面這些,繪製圖表不再是什麼難題了,剩下的只是座標的計算和柱子寬度,高度的計算了
- 下面是ondraw方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float lineInterval = (mHeight - bottomHeight) / 4f; //橫線之間的間距 縱向
float textHeight = mHeight + paddingTop - bottomHeight;//橫座標高度
//畫線
drawLine(canvas, lineInterval, textHeight);
//畫縱座標
drawYtext(canvas, lineInterval, textHeight);
//畫橫座標
float textTempStart = textStart;
drawXtext(canvas, textTempStart);
float chartTempStart = startChart;
float size = (mHeight - bottomHeight) / 100f; //比例
//畫柱子
drawBar(canvas, chartTempStart, size);
}
需要理解的地方
- 在view進行初始化的時候,我們初始化了一個ChartAnimator,其實是ObjectAnimator將0-1內生成的所有數字給了他,方便在view裡得到這些變化的值。
- 在初始化的時候,我們對動畫做了監聽,當他更新的時候,我們就呼叫了一下postInvalidate(),這句話就是讓view執行ondraw方法,通過變數來增加條形圖的高度。
- 最後還是條形圖寬度的問題,我是這樣設計的,當條形圖的數量大於6時,那麼所有的條形圖的寬度將平分整個view的寬度,然後將計算後的值得30%作為條形圖的間隔,剩下的70%的寬度就是條形圖的寬度,繪製是從左向右繪製,當條形圖的數量小於6或者等於6時,我將所有的條形圖繪製到了整個表的中間,寬度怎麼平分的大家可以檢視原始碼,具體的就不說了
- 水平滑動用到了Android的手勢,有興趣的可以看下,暫時不說這塊
原始碼下載
- 文章只貼出了一部分原始碼,更詳細的原始碼,請檢視我的demo
- 獲取原始碼方式:在公眾號:AppCode公眾號內回覆關鍵字“條形圖”,即可拿到原始碼的下載連結。
- 掃描下面的二維碼,即可關注AppCode公眾號