【问题标题】:Force BarChart Y axis labels to be integers?强制 BarChart Y 轴标签为整数?
【发布时间】:2015-04-29 11:37:42
【问题描述】:

我使用 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 等。

【问题讨论】:

  • 您的问题解决了吗?我想要同样的改变,你能帮忙吗
  • 我没有,抱歉。我忙于其他项目,最后就这样离开了。我确实意识到,对于较大的整数,这个问题不会出现,但目前没有办法让它适用于小整数。
  • 谢谢.......

标签: android bar-chart mpandroidchart


【解决方案1】:

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

很遗憾,目前无法自定义轴计算自身的方式或设置自定义标签。

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

只是一个提示:

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

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

【讨论】:

  • 正如我在问题中提到的:“我尝试使用 ValueFormatter 来舍入值,但问题是有时 Y 值不在整数值位置(例如 0.8, 1.6、2.4 等)。因此,如果我只是将它们编辑为整数,它们将不会位于正确的位置。”
  • 肯定会的。使用 ValueFormatter,您只需修改值标签中绘制的内容。您没有修改所绘制条目的值。
  • 如果我有值 '3.4' 并将其更改为 '3',那么 3 将太高。另外,如果我的值是 2.1 和 2.8,这会给我两个 2。我可以改变我的四舍五入方式,但这并不能解决问题。请参阅我更新的问题以获取更多详细信息。感谢您的帮助!
【解决方案2】:

在四处寻找没有可用的解决方案后,我决定查看 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);
    }
}

就是这样!

【讨论】:

  • 太棒了,正是我想要的,谢谢!像这样的特征也可能称为步长,或者在这种情况下可能称为最小步长,这就是我没有任何结果的搜索。
【解决方案3】:

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

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

【讨论】:

  • 这是最简单的解决方案,也提供连接。谢谢你节省了我的时间。
【解决方案4】:

这就是我解决此问题的方法。似乎 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);

【讨论】:

    【解决方案5】:

    我知道我很晚才回答,但我试图对此问题进行更多说明,以便未来的用户对此有更多了解。

    我也遇到了同样的问题。我使用MyYAxisValueFormatterY-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 否则两个。您可以根据需要自定义此行为 并通过修改do-while循环来增加标签间隔。

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

    【讨论】:

      【解决方案6】:

      我的解决方案:

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

      【讨论】:

        【解决方案7】:

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

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

        【讨论】:

          【解决方案8】:

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

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

          【讨论】:

          • 它与同事描述的问题相同,这是解决问题的可能方法,但从美学角度来看,某些用户不太喜欢它,因此它显示了固定数据,是有什么方法可以在 AxisLeft 中设置 0 - 5 - 10 - 15- 等?
          【解决方案9】:

          我遇到了同样的问题,我正在获取:

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

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

          结果:

          【讨论】:

            【解决方案10】:

            value 参数的每次更改并显示它都会导致误导性标签。 为此,您需要根据需要设置AxisMinimum()、setAxisMaximum()、setGranularity() 和setLabelCount(),然后只显示您想要的标签。

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

            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
                }
            

            Logcat:

            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。

            Logcat:

            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),事情就会变得非常混乱:

            Logcat:

            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
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-05-10
              • 1970-01-01
              • 2012-08-16
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多