Force BarChart Y axis labels to be integers?

风格不统一 提交于 2019-12-03 05:33:35

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

Pretty simple. All you need is two things:

  1. Axis value formatter

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

    int max = findMaxYValue(yourdata); // figure out the max value in your dataset
    mChart.getAxisLeft().setLabelCount(max);
    

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

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!

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.

Faisal Shaikh

My Solution:

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

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); ```
    
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!