Force BarChart Y axis labels to be integers?

后端 未结 8 752
滥情空心
滥情空心 2021-02-05 11:47

I\'ve created a BarChart using MPAndroidChart and I\'m entering the data dynamically. This means that I need my Y axis to also be determined dynamically. All of my data is repre

相关标签:
8条回答
  • 2021-02-05 12:10

    After looking around with no solution available, I've decided to look into the javadoc and found out about this method: setGranularity(float). To force the YAxis to always display integers (or any interval you want), you just need to call this:

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

    However, if the min and max values of the chart is too close, then the chart will not honor setLabelCount(), unless when is forced (which will make the labels in decimal again), so you need to call this after setting data:

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

    And that's it!

    0 讨论(0)
  • 2021-02-05 12:13

    Allright, now I see your problem. THe problem is that the YAxis (YLabels) determines the number of digits and thus the steps between each label automatically.

    Unfortunately it's currently not possible to customize how the axis computes itself or set custom labels.

    I am considering to add such a feature in the future, where the user can self define which values are drawn as the axis labels.

    Just a hint:

    The mEntries array that holds all the axis labels is public. So in general, you could modify it after it has been created. However, I am absolutely not sure how the axis will behave if you manually modify it.

    But maybe its worth a try :-) https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java

    0 讨论(0)
  • 2021-02-05 12:20

    I know that I am answering very late, but I am trying to throw some more light on this issue so that future users have a bit more knowledge regarding the same.

    I also faced the same issue. I used MyYAxisValueFormatter to display only integer value in Y-Axis. Below is the code for the same.

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

    By using this class what happens is definitely it displays the Y-Axis values in integer format but also duplicate some value. That is because of conversion of float value to integer.

    Let say for example 0.4 will be converted to 0 so there will be two or may be more 0 values in Y-Axis.

    I think this is what happening in case of @Fozefy.

    I implemented below given code to solve this issue and its work like a charm. I used setAxisMaxValue function to set a custom maximum value for Y-axis and setLabelCount to sets the number of label entries for the Y-Axis.

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

    Label interval remains one if your maximum y-value is less than 10 otherwise two. You can customize this behavior as per your requirement and also increase label interval by modifying do-while loop.

    Also make sure that you are using setLabelCount(int count, boolean force) method and passing force value to true.

    0 讨论(0)
  • 2021-02-05 12:20

    Here is the simple solution which will benefit someone who is looking for the answer.

    1. Y-Axis labels count

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

    2. Calculate maxValue

      • Get maxValue from values need to be included in the chart
      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); ```
      
    0 讨论(0)
  • 2021-02-05 12:21

    To add to the solution, if someone just wants to remove the decimal and repeated values, you can do this :

    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);
    
    0 讨论(0)
  • 2021-02-05 12:22

    This is how I resolved this issue. It seems like the y axis is always drawn 1 over the max value(if its not force it). So set the label count 2 over the max value(include zero and one over your max) then all you need to do is remove the decimal with the axis formatter. This works if all your y values are integers, not sure how it would work with decimal values.

        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);
    
    0 讨论(0)
提交回复
热议问题