1. 程式人生 > >解決MPAndroidChart-LineChart清除資料重新整理後X軸取值不準確的問題

解決MPAndroidChart-LineChart清除資料重新整理後X軸取值不準確的問題

由於專案需要使用表格,於是在Github上搜索到了一個比較好的開源控制元件。

現在我想實現一個表格,表格上每隔幾秒增加一個點,表格上只會顯示10條資料,所以效果就像動態更新資料一樣,每加一個點,X軸像左移動一個點。

但是我現在想加一個Button,每次點選後就清除掉LineChart中的DataSet,然後重新設定一個DataSet,重新載入資料。也就是說X軸重新從0開始,但是就在這個時候出現了問題,與第一次設定LineChart之前一摸一樣的程式碼,重新整理之後,X軸上顯示的數值不是我想象中的1,2,3,4…..9,10了,而是各種可能的數值,反正是帶小數的數值。

第一次載入X軸是正常的0 - 10。
這裡寫圖片描述

重新整理後X軸的值是0.0-0.8:
這裡寫圖片描述

這個問題困擾了好幾天,最後在原始碼中檢視到了蹊蹺:

XAxisRenderer.java

    @Override
    public void computeAxis(float min, float max, boolean inverted) {
        Log.e("info", "min = " + min + " max = " + max);
        Log.e("info", "mScarlX = " + mViewPortHandler.getScaleX() + " minScaleX = " + mViewPortHandler.getMinScaleX());
        // calculate the starting and entry point of the y-labels (depending on
// zoom / contentrect bounds) if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutX()) { MPPointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); MPPointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), mViewPortHandler.contentTop()); if
(inverted) { min = (float) p2.x; max = (float) p1.x; } else { min = (float) p1.x; max = (float) p2.x; } MPPointD.recycleInstance(p1); MPPointD.recycleInstance(p2); } Log.e("info", "轉換後 min = " + min + " max = " + max); Log.e("info", "***************************************************************************************************************"); computeAxisValues(min, max); }

通過檢視原始碼與除錯,發現每次我設定了X軸的最大值和最小值後,x的取值都是在這個地方算出來的,第一次設定是正常的,但是一旦重新整理資料之後,x軸的值就不正常了,原因就是mViewPortHandler這個變數。

x軸的取值具體是用矩陣計算的,這個過程我就不分析了(其實是看不懂啊┑( ̄▽  ̄)┍ )。但是我只知道,它每次計算都會跟這個mViewPortHandler物件有關係:

MPPointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop());
MPPointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), mViewPortHandler.contentTop());

最後進去看了下ViewPortHandler.java的原始碼,發現它的很多計算都與一個Matrix變數有關:

/**
     * matrix used for touch events
     */
    protected final Matrix mMatrixTouch = new Matrix();

然後又發現了這個類裡面又一個public Matrix refresh(Matrix newMatrix, View chart, boolean invalidate)方法。可以重置上面的mMatrixTouch變數。於是我就呼叫這個方法,直接new了一個Matrix進去,問題就解決了。

解決辦法:

在清除資料後,呼叫:

chart.setScaleMinima(1.0f, 1.0f);
chart.getViewPortHandler().refresh(new Matrix(), chart, true);