Mpandroidchart: how to display dynamic labels for XAxis

Created on 20 Jul 2016  路  34Comments  路  Source: PhilJay/MPAndroidChart

I am using bar chart and i am unable to display dynamic xaxis labels on the chart, so far i have been able to show only one label for all bars using value formatter, please can anyone show me how to do it. It is a good library but still not sufficient documentation for noobs. currently i am using this code:

XAxis xval = barChart.getXAxis();
        xval.setDrawLabels(true);
        xval.setValueFormatter(new AxisValueFormatter() {
            @Override
            public String getFormattedValue(float value, AxisBase axis) {
                return  "Label";
            }

            @Override
            public int getDecimalDigits() {
                return 0;
            }
        });

    xval.setPosition(XAxis.XAxisPosition.BOTTOM);
    xval.setDrawGridLines(false);

Most helpful comment

There's also an IndexAxisValueFormatter class if you have a simple lookup.

// Look-up table
final String[] weekdays = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

// Set the value formatter
XAxis xAxis = chart.getXAxis();
xAxis.setValueFormatter(new IndexAxisValueFormatter(weekdays));

All 34 comments

Hi man, I have the same question, if you find the answer can you share it ? :)

I'll share it.. don't worry..

Hi, I am facing the very same problem. Details here #2043

@Wadoks @developer1011
right now i am exploring source to find any clue how i can do it, but there is a kind of work around that i did. rather than displaying labels in the bottom i displayed it on top of the bars in bar chart by implementing valueFormatter on dataset instance..

ArrayList<BarEntry> entries = new ArrayList<>();
    entries.add(new BarEntry(0, 4, "Label 1"));
    entries.add(new BarEntry(1, 3, "Label 2"));
    entries.add(new BarEntry(2, 4, "Label 3"));
    entries.add(new BarEntry(3, 6, "Label 4"));
    entries.add(new BarEntry(4, 7, "Label 5"));

dataset.setValueFormatter(new ValueFormatter() {
        @Override
        public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
            //rather than diaplaying value show label 
            return entry.getData().toString();
        }
    });

@xainbutt thanks for posting the code. Having the labels on top of the bar is a good idea.

I tried a different workaround. By extending the AxisValueFormatter. Here appNames is a String array having labels. You can pass this String array to the instance of class extending AxisValueFormatter. Then within the getFormattedValue method returning the label value based on the label array length, also adding the x-Axis float value to a temporary ArrayList.
I like your solution.

@Override
    public String getFormattedValue(float value, AxisBase axis) {
        String xValue = "";
        if (xValues.size() <= appNames.length) {
            xValues.add(value);
        }
        int index = xValues.indexOf(value);
        if (index >=0 && index < appNames.length)
            xValue = appNames[index];
        return xValue;
    }

@developer1011
you are implementing AxisValueFormatter, that would diaplay labels on the xAxis rather than on top of the bars. what i did was to implement ValueFormatter on the BarDataSet class..
can you post the remaining code and an image of the graph if possible..??

thanks @xainbutt , it works great on my project !

But i have a question, how can i change the default label on each bar to show the value ? (the same value that was showed on top before)

I dont think i understood your question well, are you talking about the "Label 1" value that was passed to the instance..?? @JulioCesarSiqueira
Try this, it will show label as well as your value..

dataset.setValueFormatter(new ValueFormatter() {
            @Override
            public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {

                return entry.getData().toString()+ "(" + entry.getY() + ")";
            }
        });

Sorry, i coudn't explain my question. Here is my project :

appprint height="400"

Inside the red circle, there are my XAxys, with the X values.

Is there a way to substitute these values and put Labels, the same labels that are on top of each bars ? (rock, punk etc) ? Is the same string value which i can get with entry.getData().toString()

correct me if i am wrong,you want to display labels that are on top of the bars in x axis..?? @JulioCesarSiqueira

Yes ! Is that possible ?

As far as i searched or looked at source, i couldn't find anything..and that's the reason i created this issue

alright guys, i just found how we can display labels on the x axis... I hope i'm not too late..
@Wadoks @developer1011 @JulioCesarSiqueira

First have your labels in a string array.
Get xAxis
Use ValueFormatterInterface on xAxis

final String[] ds = new String[7];
    ds[0]="Lights";
    ds[1]="Generator";
    ds[2]="Ups";
    ds[3]="Ac";
    ds[4]="Lights";
    ds[5]="Fan";
    ds[6]="Ac";


    XAxis xval = barChart.getXAxis();
    xval.setDrawLabels(true);
    xval.setValueFormatter(new AxisValueFormatter() {
        @Override
        public String getFormattedValue(float value, AxisBase axis) {
            Log.i("zain", "value " + value);
            return ds[Math.round(value)];
        }

        @Override
        public int getDecimalDigits() {
            return 0;
        }
    });

Have a look at the IAxisValueFormatter wiki.

But there is a problem with this, if we zoom the chart the labels that refer the bars dont quite follow them..then it looks there are some bars that dont have labels.. @PhilJay
and one more thing, how can i make chart to scroll when there is lots of data rather than shrinking bars..And thank you for this amazing library..
screenshot_2016-08-13-00-33-56 1

@xainbutt i got it working like you said, but llet say you change the dataset , and refresh the chart, the x axis wont refresh and you would get IndexOutOfBoundsException , please check out my problem https://github.com/PhilJay/MPAndroidChart/issues/2380

@saiidabs its been a while i used mpcharts... as far as i remember i solved this with another thing that i cant remember right now..i'll post something as soon as i get my hands on my code because its in another computer... and sorry for coming late to the party...

I am facing the same problem. Did anyone find a perfect solution to the problem?

@muzammil22 i had the same problem , here is how i solved it. waterRecs is the Arraylist with the X values i want

   XAxis xAxis = barchart.getXAxis();
   xAxis.setValueFormatter(new IAxisValueFormatter()
    {

        @Override
        public String getFormattedValue(float value, AxisBase axis)
        {
            System.out.println(value);
            if(((int)value)<waterRecs.size())
            {
                return  (waterRecs.get((int)value).getDate());
            }
            else
            {
                return "";
            }
        }


    });

Thanks alot for the help @saiidabs

Version 3.0 is unusable..... I try to move from 2.2 to 3.0 and I waste 2-3 hours trying to fix the X label which now are simply not working at all. And this interface IAxisValueFormatter. I want to display string label what to do with that float argument ? ?????

@Svinqvai you cast the float argument into an INT. its used as your index value

I am facing the same issue in LineChart and put a try/catch block

//xlabels is List<String> 
xAxis.setValueFormatter(new IAxisValueFormatter() {

            @Override
            public String getFormattedValue(float value, AxisBase axis) {
                try{
                    return xLabels.get((int)value);
                }catch(Exception ex){
                    String msg = ex.getMessage();
                    String joined =TextUtils.join(", ", xLabels);
                    String valuesJoined = TextUtils.join(", ", values);
                    Log.v("CHART_XAXIS",joined);
                    Log.v("CHART_ENTRIES",valuesJoined);
                    Log.v("ERROR_INDEX",String.valueOf(value));
                    return "";
                }

            }

        });

and found some weird stats in log

V/CHART: 2017, 2016, 2015, 2014, 2013 
V/CHART_ENTRIES: 311, 0, 0, 0, 0 
V/ERROR_INDEX: 5.0

V/CHART: Mon, Sun, Sat, Fri, Thu, Wed, Tue V/CHART_ENTRIES: 311, 0, 0, 0, 0,3,7 V/ERROR_INDEX: 11.0
but the issue is by returning empty string my the chart gets expended and where is set the chart.setVisibleXRangeMaximum(5); I get only one value shown at a time and the charts boundary goes out of bound. even the chart has 3 values to represent on xaxis. and even the last value on the xAxis is not displayed.

I am Facing an problem creating an Dynamic label in that library....

My labels are also dynamic as they render by onContextMenu item

Hi Faisal,
Could you send your sample code for dynamic label in that library

There's also an IndexAxisValueFormatter class if you have a simple lookup.

// Look-up table
final String[] weekdays = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

// Set the value formatter
XAxis xAxis = chart.getXAxis();
xAxis.setValueFormatter(new IndexAxisValueFormatter(weekdays));

@mhassanpur,
I have implemented exactly what you posted in Group bar chart, but it is not working in that case.
I am using Combined chart with line graph and group bar chart.

Could you please help me for my case?

@mhassanpur
Yes your solution really works with the barchart. You save my life 馃拑

I am trying to split the label text in two lines if it is too big, for example if the label text is more than 15 characters in length. But "\n" is acting like "\t". Please can anyone help??

For the com.github.PhilJay:MPAndroidChart:v3.0.3
I am using a label list:
final List list_x_axis_name = new ArrayList<>();
list_x_axis_name.add("label1");
list_x_axis_name.add("label2");
list_x_axis_name.add("label3");
list_x_axis_name.add("label4");
list_x_axis_name.add("label5");

and setting
BarChart chartBar = (BarChart) findViewById(R.id.chartBar);
XAxis xAxis = chartBar.getXAxis();
xAxis.setGranularity(1f);
xAxis.setCenterAxisLabels(true);
xAxis.setLabelRotationAngle(-90);
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
if (value >= 0) {
if (value <= list_x_axis_name.size() - 1) {
return list_x_axis_name.get((int) value);
}
return "";
}
return "";
}
});

I am facing issue in setting x axis value for bargraph in listview for multiple item. not able to get how to replace x axis value for multiple item view . Below code is used :

private BarData generateDataBar(List result) {
xAxisLabel = new ArrayList<>();
Log.d("GRAPH", "graph entry data size" +result.size());
ArrayList entries = new ArrayList();
for (int i = 0; i < result.size(); i++) {
int value;
try {
value = (int) Double.parseDouble(result.get(i).getQuantity());
}catch (Exception e){
e.printStackTrace();
value=0;
}
entries.add(new BarEntry(i, value));
// set x axis value in array list and pass this array in set adapter constructor
xAxisLabel.add(result.get(i).getMonth());
}

    BarDataSet d = new BarDataSet(entries,  "(Quantity) " + result.get(0).getName());
    d.setColors(ColorTemplate.VORDIPLOM_COLORS);
    d.setHighLightAlpha(255);
    d.setBarShadowColor(Color.rgb(203, 203,203));

    ArrayList<IBarDataSet> sets= new ArrayList<>();
    sets.add(d);

    BarData cd = new BarData(sets);
    cd.setBarWidth(0.9f);
    return cd;
}

//bar chart item
listRes.add(new BarChartItem(generateDataBar(customerResult), getActivity(), xAxisLabel));

// in item view set x axis value
IAxisValueFormatter formatter = new IAxisValueFormatter() {

        @Override
        public String getFormattedValue(float value, AxisBase axis) {
            return xAxisLabel.get((int) value);
        }


    };

Hi, i have same problem.

private void showChart(final ArrayList<Pair<String,Integer>> dataObjects){
        ArrayList<Entry> entries = new ArrayList<>();
        for (int i = 0; i < dataObjects.size(); i++) {
            entries.add(new Entry(i, dataObjects.get(i).second));
        }

        LineDataSet dataSet = new LineDataSet(entries, "Pendapatan"); // add entries to dataset
        dataSet.notifyDataSetChanged();
        dataSet.setColor(Color.BLUE);
        dataSet.setValueTextColor(Color.RED);

        LineData lineData = new LineData(dataSet);
        lineData.notifyDataChanged();
        chart.setData(lineData);
        chart.notifyDataSetChanged();
        chart.invalidate();
        chart.getXAxis().setLabelRotationAngle(-90);
        chart.getXAxis().setValueFormatter(null);
        chart.getXAxis().setValueFormatter((value, axis) -> dataObjects.get((int) value).first);
        chart.invalidate();

}

For the first time call showChart() method with argument the ArrayList with 7 items. Then for the second times i call showChart() method with argument with 30 items, it is error which is
IndexOutOfBoundsException: Index: 10, Size: 7

Why dataObjects inside lambda expression above change? i have set final keyword in parameter.

But there is a problem with this, if we zoom the chart the labels that refer the bars dont quite follow them..then it looks there are some bars that dont have labels.. @PhilJay
and one more thing, how can i make chart to scroll when there is lots of data rather than shrinking bars..And thank you for this amazing library..
screenshot_2016-08-13-00-33-56 1

Hi, Kindly may I know, how to set label on above graphic, like on your project "AC Home",, "zain Light", etc??

Was this page helpful?
0 / 5 - 0 ratings

Related issues

OnlyInAmerica picture OnlyInAmerica  路  3Comments

galex picture galex  路  3Comments

AndroidJiang picture AndroidJiang  路  3Comments

Nima9Faraji picture Nima9Faraji  路  3Comments

DarkHelmet67 picture DarkHelmet67  路  3Comments