1. 程式人生 > >android條形圖繪製以及加入動畫,並且支援水平滑動

android條形圖繪製以及加入動畫,並且支援水平滑動

閒話

Android 圖表的繪製,無非是view的繪製,只有掌握了view的繪製流程,那麼一個條形圖,也沒有什麼可難繪製的,那為什麼會有人覺得比較難呢,其實是自己內心裡懼怕他,於是每次出現圖表需求,想都不用想就選擇第三方的,也就是別人寫好的,當然,這也沒有什麼,大家都會用的,也不只是你一個人在用,目前在github上star最多的可能就是MPAndroidChart了,做的的確很強大,但是再強大,有時候也會有那麼一丟丟的不符合我們自己的需求,這個時候,真是讓人哭笑不得啊,用的話,又不能達到產品的需求,不用吧,自己好像又沒有什麼思路,於是僵住了。

我花了點時間大致的看了下MPAndroidChart原始碼,的確內容很多,今天,就用自己的思想以及MPAndroidChart的思想相結合來寫一個比較簡單的條形圖,這樣也是對繪製view的一次學習吧

效果

  1. 不可滑動效果:

不可滑動

  1. 可滑動效果:

可滑動

圖片看起來有點失真,還伴隨點卡頓,這是由於錄影是電腦和手機連線不穩定造成的,真實的動畫是不會有任何卡頓的。

理清思路

首先我們得理清思路,如何才能繪製出一個條形圖,不能連思路都沒有就去做,這樣真的很難下手。

1. 初始化操作

首先,圖表是自定義view,繼承自view,所以該重寫的方法都要重寫。

  1. 當圖表建立時,我們都需要準備什麼,第一個當然是畫筆Paint了,這個時候我們只需要對畫筆進行初始化,什麼顏色啊,填充方式啊等等。
  2. 除了初始化畫筆Paint外,我們還需要初始化的,就是動畫了,因為我們需要給條形圖加入動畫,這個時候,問題來了,動畫和條形圖如何結合起來?
  3. 能讓條形圖動起來的動畫當然是ValueAnimator或者ObjectAnimator了,這兩個動畫其實是一個東西,最終都是ValueAnimator,所以用哪個其實都可以實現,我用的是ObjectAnimator,因為MPAndroidChart也用的是ObjectAnimator。
  4. 究竟動畫怎麼才能和條形圖結合呢?
 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. 測量高度

  1. 在onLayout方法裡,可以得到view的高度和寬度,因為我們需要在後面計算每個條形圖佔整個控制元件高度的百分比

  2. 在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. 開始繪製

  1. view的繪製全在onDraw方法裡,這個時候就用到onDraw方法中的canvas了,條形圖其實也就是矩形,所以也很好繪製,這個時候,我們需要了解的就是canvas的方法,他都能繪製些什麼,方法中的引數又是什麼意思並且代表著什麼,只有搞清楚了這些,我們才能正式開始下手繪製,否則,我們還是無從下手。
  2. canvas.drawRect(),這個方法其實才是我們重點要掌握的,他就是繪製矩形的方法,首先,你需要知道,他的引數的意義
  3. 他需要的引數為:(float left, float top, float right, float bottom,Paint paint ),乍一看,引數太多,看都不想看了,彆著急,他很簡單的,只不過就是座標而已,上下左右嘛,這有什麼難的,那麼這又分別代表著什麼呢,搞清楚這些我們才好下手呀。
  4. left表示矩形的左邊到view最左邊的距離,而不是螢幕的左邊,這個要搞清楚,top也就表示著矩形的上邊到view的頂部距離,而不是螢幕頂部,right是矩形的右邊到view的左邊距離,bottom是矩形的下邊到view的頂部的距離
  5. 只要你搞清楚了上面這些,繪製圖表不再是什麼難題了,剩下的只是座標的計算和柱子寬度,高度的計算了
  6. 下面是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);

    }

需要理解的地方

  1. 在view進行初始化的時候,我們初始化了一個ChartAnimator,其實是ObjectAnimator將0-1內生成的所有數字給了他,方便在view裡得到這些變化的值。
  2. 在初始化的時候,我們對動畫做了監聽,當他更新的時候,我們就呼叫了一下postInvalidate(),這句話就是讓view執行ondraw方法,通過變數來增加條形圖的高度。
  3. 最後還是條形圖寬度的問題,我是這樣設計的,當條形圖的數量大於6時,那麼所有的條形圖的寬度將平分整個view的寬度,然後將計算後的值得30%作為條形圖的間隔,剩下的70%的寬度就是條形圖的寬度,繪製是從左向右繪製,當條形圖的數量小於6或者等於6時,我將所有的條形圖繪製到了整個表的中間,寬度怎麼平分的大家可以檢視原始碼,具體的就不說了
  4. 水平滑動用到了Android的手勢,有興趣的可以看下,暫時不說這塊

原始碼下載

  1. 文章只貼出了一部分原始碼,更詳細的原始碼,請檢視我的demo
  2. 獲取原始碼方式:在公眾號:AppCode公眾號內回覆關鍵字“條形圖”,即可拿到原始碼的下載連結。
  3. 掃描下面的二維碼,即可關注AppCode公眾號

AppCode