19

我已经使用 MPAndroidChart 创建了一个 BarChart,并且我正在动态输入数据。这意味着我还需要动态确定我的 Y 轴。我的所有数据都表示为整数,但是 Y 轴有时将图例显示为带 1 个小数点的十进制值。

我尝试使用 ValueFormatter 对值进行舍入,但问题是有时 Y 值不在整数值位置(例如 0.8、1.6、2.4 等)。因此,如果我只是将它们编辑为整数,它们将不会位于正确的位置。

无论如何,我可以强制 BarChart 仅在整数位置显示值吗?如果它跳过一些就可以了,事实上我希望它在值变大时。

编辑:当我说整数不在正确的位置时,我的意思是一旦我修改了每个标签显示的内容,它们就不是“正确的”。在我的示例中,我有 5 个条形显示值 3、4、2、3、2。第一个图像是“默认”,第二个是我编辑值格式化程序后的图像:

myBarChart.getYLabels().setFormatter(new ValueFormatter()
{
    @Override
    public String getFormattedValue(float v)
    {
        return ((int) v)+"";
    }
});

在此处输入图像描述 在此处输入图像描述

正如我们从这些图像中看到的那样,我的整数值不在它们应该在的位置(并且有两个“2”)。在此示例中,我将其除以显示值 0、1、2、3、4。如果我有更多数据,我希望它足够聪明,只显示我有空间的值,所以例如,如果数据包含 0-50 的值,它会显示类似 0,10,20,30 ,40,50 或可能 0,15,30,45 等。

4

10 回答 10

15

好的,现在我看到了你的问题。问题是(YLabels)自动YAxis确定位数,从而确定每个标签之间的步骤。

不幸的是,目前无法自定义轴如何计算自身或设置自定义标签。

我正在考虑在未来添加这样的功能,用户可以自行定义哪些值被绘制为轴标签。

只是一个提示:

包含所有轴标签的mEntries数组是公共的。因此,一般来说,您可以在创建后对其进行修改。但是,如果您手动修改它,我绝对不确定轴的行为方式。

但也许值得一试:-) https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java

于 2015-02-26T23:28:39.003 回答
13

在没有解决方案的情况下环顾四周后,我决定查看 javadoc 并发现了这种方法:setGranularity(float). 要强制 YAxis 始终显示整数(或您想要的任何间隔),您只需要调用它:

yAxisLeft.setGranularity(1.0f);
yAxisLeft.setGranularityEnabled(true); // Required to enable granularity

但是,如果图表的最小值和最大值太接近,那么图表将不会尊重setLabelCount(),除非强制使用时(这会使标签再次变为十进制),因此您需要在设置数据后调用它:

private void calculateMinMax(BarLineChartBase chart, int labelCount) {
    float maxValue = chart.getData().getYMax();
    float minValue = chart.getData().getYMin();

    if ((maxValue - minValue) < labelCount) {
        float diff = labelCount - (maxValue - minValue);
        maxValue = maxValue + diff;
        chart.getAxisLeft().setAxisMaximum(maxValue);
        chart.getAxisLeft().setAxisMinimum(minValue);
    }
}

就是这样!

于 2017-01-22T07:57:29.900 回答
8

很简单。你只需要两件事:

  1. 轴值格式化程序

    mChart.getAxisLeft().setValueFormatter(new ValueFormatter() {
        @Override
        public String getFormattedValue(float value) {
            return String.valueOf((int) Math.floor(value));
        }
    });
    
  2. 轴标签计数

    int max = findMaxYValue(yourdata); // figure out the max value in your dataset
    mChart.getAxisLeft().setLabelCount(max);
    
于 2015-05-20T22:18:14.377 回答
6

这就是我解决这个问题的方法。似乎 y 轴总是在最大值上绘制 1(如果它不强制它)。因此,将标签计数 2 设置为最大值(包括最大值零和一),那么您需要做的就是使用轴格式化程序删除小数点。如果您的所有 y 值都是整数,则此方法有效,不确定如何处理十进制值。

    barChart.getAxisLeft().setLabelCount(maxYvalue + 2, true);
    barChart.getAxisLeft().setAxisMinValue(0f);
    barChart.getAxisLeft().setAxisMaxValue(maxYvalue + 1);
    YAxisValueFormatter customYaxisFormatter = new YAxisValueFormatter() {
        @Override
        public String getFormattedValue(float value, YAxis yAxis) {
            return String.valueOf((int)value);
        }
    };
    barChart.getAxisLeft().setValueFormatter(customYaxisFormatter);
于 2016-03-14T06:07:27.987 回答
3

我知道我回答得很晚,但我试图对这个问题提出更多的看法,以便未来的用户对此有更多的了解。

我也面临同样的问题。我MyYAxisValueFormatter以前只显示整数值Y-Axis。下面是相同的代码。

public class MyYAxisValueFormatter implements YAxisValueFormatter {

    private DecimalFormat mFormat;

    public MyYAxisValueFormatter () {
        mFormat = new DecimalFormat("###,###,##0");
    }

    @Override
    public String getFormattedValue(float value, YAxis yAxis) {
        // write your logic here
        // access the YAxis object to get more information
        return mFormat.format(value);
    }
}

通过使用这个类,它肯定会以整数格式显示 Y 轴值,但也会重复一些值。那是因为浮点值转换为整数。

假设例如 0.4 将被转换为 0,因此 Y 轴中将有两个或可能更多的 0 值。

我认为这就是@Fozefy.

我在下面实现了给定的代码来解决这个问题,它的工作就像一个魅力。我使用setAxisMaxValue函数为 Y 轴设置自定义最大值并setLabelCount设置 Y 轴的标签条目数。

    YAxis yAxis = chart.getAxis(YAxis.AxisDependency.LEFT);

    // Minimum section is 1.0f, could be 0.25f for float values
    float labelInterval = 1.0f / 2f;

    int sections; //No of sections in Y-Axis, Means your Highest Y-value.
    do {
        labelInterval *= 2; //Interval between labels in Y-Axis
        sections = ((int) Math.ceil(chart.getYMax() / labelInterval));
    } while (sections > 10);

    // If the ymax lies on one of the top interval, add another one for some spacing
    if (chart.getYMax() == sections * labelInterval) {
        sections++;
    }

    yAxis.setAxisMaximum(labelInterval * sections);
    yAxis.setLabelCount(sections + 1, true);

如果您的最大 y 值小于 10,则标签间隔保持为 1,否则为 2。您可以根据您的要求自定义此行为,还可以通过修改 do-while 循环来增加标签间隔。

还要确保您正在使用setLabelCount(int count, boolean force)方法并将force值传递给true.

于 2016-08-10T10:49:18.387 回答
0

值参数的每一次变化和显示都会导致误导性的标签。出于这个原因,您需要根据需要设置轴最小值()、设置轴最大值()、设置粒度()和设置标签计数(),然后只显示您想要的标签。

例如,如果你想显示秒,你可以像这样设置这些参数:

YAxis yAxis = chartName.getAxisLeft();
yAxis.setAxisMinimum(0);//start from 0am
yAxis.setAxisMaximum(86400);//seconds of day
yAxis.setGranularityEnabled(true);
yAxis.setGranularity(1);//values interval
yAxis.setLabelCount(25, true);//from 0 to 24

这会将 ValueFormatter 中的 value 参数设置为 25 个部分,这将是相等的,因此当您除以 3600 得到小时时,它将是偶数。

chartNmae.setValueFormatter(new ValueFormatter() {
    @Override
    public String getFormattedValue(float value) {
        Log.i("Y axis: ", value / 3600 + "h");

        int hour = (int)value / 3600;

        //if you only want to show some of the values/labels then filter them
        return hour % 2 == 0 ? hour + ":00" : "";//return even hour or make the label empty
    }

日志猫:

Y axis:: 0.0h
Y axis:: 1.0h
Y axis:: 2.0h
Y axis:: 3.0h
Y axis:: 4.0h
Y axis:: 5.0h
Y axis:: 6.0h
Y axis:: 7.0h
Y axis:: 8.0h
Y axis:: 9.0h
Y axis:: 10.0h
Y axis:: 11.0h
Y axis:: 12.0h
Y axis:: 13.0h
Y axis:: 14.0h
Y axis:: 15.0h
Y axis:: 16.0h
Y axis:: 17.0h
Y axis:: 18.0h
Y axis:: 19.0h
Y axis:: 20.0h
Y axis:: 21.0h
Y axis:: 22.0h
Y axis:: 23.0h
Y axis:: 24.0h

您在图表中的值/条目是相同的,可能是浮动的,但标签将是整数,并将设置在正确的位置。因此,如果数据集中的条目是 36600(上午 10:10),它应该出现在上午 10:00 以上的 1/6 处。

但是,如果我们将轴最大值稍微更改为 setAxisMaximum(86000),那么 ValueFormatter 将传递带有小数点后分数的参数。我们仍然可以通过向下舍入 ValueFormatter 参数(值)并将其作为标签返回来获得偶数分,但与其关联的值会稍微显示如下,现在上午 10:10(36600 数据集条目)将出现在 10:00 标签旁边(不是1/6 以上),因为我们将标签实际值四舍五入,但将其显示在轴上的保留位置。这就像把你的手表放在后面 10 分钟然后看着它。它可能显示上午 10:00,但实际上是上午 10:10。

日志猫:

Y axis:: 0.0h
Y axis:: 0.9953703h
Y axis:: 1.9907407h
Y axis:: 2.9861112h
Y axis:: 3.9814813h
Y axis:: 4.9768515h
Y axis:: 5.9722223h
Y axis:: 6.9675927h
Y axis:: 7.962963h
Y axis:: 8.958334h
Y axis:: 9.953705h
Y axis:: 10.949075h
Y axis:: 11.944445h
Y axis:: 12.939815h
Y axis:: 13.9351845h
Y axis:: 14.930554h
Y axis:: 15.925924h
Y axis:: 16.921295h
Y axis:: 17.916664h
Y axis:: 18.912035h
Y axis:: 19.907406h
Y axis:: 20.902779h
Y axis:: 21.89815h
Y axis:: 22.89352h
Y axis:: 23.888891h

如果我们将最大值更改为 setAxisMaximum (60000),事情就会变得非常混乱:

日志猫:

Y axis:: 0.0h
Y axis:: 0.6944444h
Y axis:: 1.3888888h
Y axis:: 2.0833333h
Y axis:: 2.7777777h
Y axis:: 3.4722223h
Y axis:: 4.1666665h
Y axis:: 4.861111h
Y axis:: 5.5555553h
Y axis:: 6.25h
Y axis:: 6.9444447h
Y axis:: 7.638889h
Y axis:: 8.333333h
Y axis:: 9.027778h
Y axis:: 9.722222h
Y axis:: 10.416667h
Y axis:: 11.111111h
Y axis:: 11.805555h
Y axis:: 12.5h
Y axis:: 13.194445h
Y axis:: 13.888889h
Y axis:: 14.583333h
Y axis:: 15.277778h
Y axis:: 15.972222h
Y axis:: 16.666666h
于 2021-08-19T07:09:59.700 回答
0

这是一个简单的解决方案,它将使正在寻找答案的人受益。

  1. Y 轴标签计数

    barChart.getAxisLeft().setLabelCount(7, true); //if you want 6 labels then value should be 7

  2. 计算maxValue

    • 从值中获取maxValue需要包含在图表中
    int maxValueMod = (maxValue + 2) % 6; //calc mod, here 2 is to display Legend and 6 is no of labels
    maxValue = maxValue + (6-maxValueMod); // calculate final maxValue to set in barchart
    barChart.getAxisLeft().setAxisMaximum(maxValue+2); ```
    
于 2019-08-07T05:46:58.707 回答
0

我的解决方案:

mChart.getAxisLeft().setValueFormatter(new ValueFormatter() {
    @Override
    public String getFormattedValue(float value) {
        return String.valueOf((int) Math.floor(value));
    }
});

int max = (int) mChart.getData().getYMax(); 
mChart.getAxisLeft().setLabelCount(max);
于 2019-03-23T23:23:30.167 回答
0

我有同样的问题,我得到:

没有修复的图表

要仅显示“整数”(在本例中为“10”),请尝试以下操作:

chart.axisLeft.valueFormatter = object : ValueFormatter() {
    override fun getFormattedValue(value: Float): String {
        return if (value == value.toInt().toFloat()) {
            (floor(value.toDouble()).toInt()).toString()
        } else {
            ""
        }
    }
}

结果:

带有修复的图表

于 2021-05-03T20:14:57.437 回答
0

要添加到解决方案中,如果有人只想删除小数和重复值,您可以这样做:

IAxisValueFormatter yAxisValueFormatter = new IAxisValueFormatter() {
      @Override
      public String getFormattedValue(float v, AxisBase axisBase) {
//check for decimal value
        if (v - (int) v != 0) {
          return "";
        } else {
          return String.valueOf((int) v);
        }
      }
    }; 
    leftAxis.setValueFormatter(yAxisValueFormatter);
    rightAxis.setValueFormatter(yAxisValueFormatter);
于 2019-11-12T23:46:02.577 回答