Android学习笔记-解决hellocharts折线图由于特殊数据不能展示的问题

前两天修改一个项目的BUG:
使用hellocharts展示了一个饼图,点击饼图的一项再用折线图展示饼图中每项具体数据。
发现问题:饼图中现有数据,点击之后折线图不能展示数据。
通过查看数据源发现:不能展示图片的情况有两种:
1. 折线图所有数据一样:例:{7,7,7}
2. 折线图只有一个数据,例:{10}

通过debug调试发现:在计算RawX,RawY会出现pixelOffset为NaN的问题。

  /**
     * Translates chart value into raw pixel value. Returned value is absolute pixel X coordinate. If this method
     * return
     * 0 that means left most pixel of the screen.
     */
    public float computeRawX(float valueX) {
        // TODO: (contentRectMinusAllMargins.width() / currentViewport.width()) can be recalculated only when viewport
        // change.
        final float pixelOffset = (valueX - currentViewport.left) * (contentRectMinusAllMargins.width() /
                currentViewport.width());
        return contentRectMinusAllMargins.left + pixelOffset;
    }

    /**
     * Translates chart value into raw pixel value. Returned value is absolute pixel Y coordinate. If this method
     * return
     * 0 that means top most pixel of the screen.
     */
    public float computeRawY(float valueY) {
        final float pixelOffset = (valueY - currentViewport.bottom) * (contentRectMinusAllMargins.height() /
                currentViewport.height());
        return contentRectMinusAllMargins.bottom - pixelOffset;
    }

先看如何让解决问题2的:
当所有点都一样的时候:computeRawY会为NaN,原因是:

    private void calculateMaxViewport() {
        tempMaximumViewport.set(Float.MAX_VALUE, Float.MIN_VALUE, Float.MIN_VALUE, Float.MAX_VALUE);
        LineChartData data = dataProvider.getLineChartData();

        for (Line line : data.getLines()) {
            // Calculate max and min for viewport.
            for (PointValue pointValue : line.getValues()) {
                if (pointValue.getX() < tempMaximumViewport.left) {
                    tempMaximumViewport.left = pointValue.getX();
                }
                if (pointValue.getX() > tempMaximumViewport.right) {
                    tempMaximumViewport.right = pointValue.getX();
                }
                if (pointValue.getY() < tempMaximumViewport.bottom) {
                    tempMaximumViewport.bottom = pointValue.getY();
                }
                if (pointValue.getY() > tempMaximumViewport.top) {
                    tempMaximumViewport.top = pointValue.getY();
                }

            }
        }
    }

这个方法计算Y轴最大值最小值,当所有数据一样,计算出的bottom和top相等,导致
computeRawY中currentViewport.height()获取的值为0;所以修改如下:

private void calculateMaxViewport() {
        tempMaximumViewport.set(Float.MAX_VALUE, Float.MIN_VALUE, Float.MIN_VALUE, Float.MAX_VALUE);
        LineChartData data = dataProvider.getLineChartData();

        for (Line line : data.getLines()) {
            // Calculate max and min for viewport.
            for (PointValue pointValue : line.getValues()) {
                if (pointValue.getX() < tempMaximumViewport.left) {
                    tempMaximumViewport.left = pointValue.getX();
                }
                if (pointValue.getX() > tempMaximumViewport.right) {
                    tempMaximumViewport.right = pointValue.getX();
                }
                if (pointValue.getY() < tempMaximumViewport.bottom) {
                    tempMaximumViewport.bottom = pointValue.getY();
                }
                if (pointValue.getY() > tempMaximumViewport.top) {
                    tempMaximumViewport.top = pointValue.getY();
                }

            }
        }
        if (tempMaximumViewport.top == tempMaximumViewport.bottom) {//解决最大值最小值相等时,图不能展示问题
            tempMaximumViewport.top = tempMaximumViewport.top * 2;
            tempMaximumViewport.bottom = 0;
        }
    }

这样所有值都相等,可以在图中间画出一条直线。

再看问题一:
由于只有一个点,computeRawX中的currentViewport.width()为初始值,即min,这样computeRawX中的currentViewport算出来同样为NaN,修改代码如下:

public float computeRawX(float valueX) {
        // TODO: (contentRectMinusAllMargins.width() / currentViewport.width()) can be recalculated only when viewport
        // change.

        final float pixelOffset = (valueX - currentViewport.left) * (contentRectMinusAllMargins.width() /
                currentViewport.width());
        if (Float.isNaN(pixelOffset)||Float.isInfinite(pixelOffset)) {
            return contentRectMinusAllMargins.left + 0;

        }
        return contentRectMinusAllMargins.left + pixelOffset;
    }

判断当算出的pixelOffset为NaN的时候直接返回contentRectMinusAllMargins.left。
好了以上两处修改就能解决折线图由于特殊数据(一条数据/数据相同)时不能展示的问题。
看上去修改的代码很简单,其实这里主要是源码的阅读和代码的跟踪。如何找到这两处还是花费了不少时间和精力的。
所以记下来,以供同样出现此问题的朋友参考。

你可能感兴趣的:(android)