解决MPAndroidChart-LineChart清除数据刷新后X轴取值不准确的问题

直接点击查看解决办法

由于项目需要使用表格,于是在Github上搜索到了一个比较好的开源控件。

现在我想实现一个表格,表格上每隔几秒增加一个点,表格上只会显示10条数据,所以效果就像动态更新数据一样,每加一个点,X轴像左移动一个点。

但是我现在想加一个Button,每次点击后就清除掉LineChart中的DataSet,然后重新设置一个DataSet,重新加载数据。也就是说X轴重新从0开始,但是就在这个时候出现了问题,与第一次设置LineChart之前一摸一样的代码,刷新之后,X轴上显示的数值不是我想象中的1,2,3,4…..9,10了,而是各种可能的数值,反正是带小数的数值。

第一次加载X轴是正常的0 - 10。
解决MPAndroidChart-LineChart清除数据刷新后X轴取值不准确的问题_第1张图片

刷新后X轴的值是0.0-0.8:
解决MPAndroidChart-LineChart清除数据刷新后X轴取值不准确的问题_第2张图片

这个问题困扰了好几天,最后在源码中查看到了蹊跷:

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);

你可能感兴趣的:(Android,源码分析和原创代码)