ValueFormatter throws IndexOutOfBoundsException - android

I have a small problem. I'm trying to make a listView of BarCharts, where xAxis represents categories, and yAxis - cost.
Here is my data.
entry
entries.add(new BarEntry(xAxis, cost, categoryName));
xAxis is just a position in chart, I put category name as 3rd parameter. Then I put it in array list of BarData
ArrayList<BarData> months = new ArrayList<>();
BarDataSet set = new BarDataSet(entries, monthName);
ArrayList<IBarDataSet> dataSets = new ArrayList<>();
dataSets.add(set);
BarData barData = new BarData(dataSets);
months.add(barData);
Then in adapter I set value formatter
BarData data = getItem(position);
...
xAxis.setValueFormatter(new MyValueFormatter(data.getDataSetByIndex(0)));
and in MyValueFormatter I'm trying to get category name from entry and set it as xAxis value.
public class MyValueFormatter implements IAxisValueFormatter {
private IBarDataSet mDataSet;
public StatisticByMonthValueFormatter(IBarDataSet data) {
mDataSet = data;
}
#Override
public String getFormattedValue(float value, AxisBase axis) {
return (String) mDataSet.getEntryForIndex((int) value).getData();
}
}
This woks, but sometimes when I'm scrolling list view I get
java.lang.IndexOutOfBoundsException: Invalid index 4, size is 2.
I know, that bug in the getFormattedValue method in MyValueFormatter, but i don't understand how can I fix this, or how implement this in the right way?

DataSet#getEntryForIndex(int index)
is the wrong method to call here. Entry in a DataSet are stored in a backing array and this method will get the Entry at that index in the backing array. This doesn't always correspond to the Entry for that x-value (the x-value on the chart). Hence, the IndexOutOfBoundsException.
You would want to do something this instead:
return (String) mDataSet.getEntryXPos(float value).getData();
See the javadoc for DataSet for further explanation

Related

MPAndroidChart - wrong values in getFormattedValue method. Where they come from?

I am working with a project which is using MPAndroidChart library which makes me really crazy, I want to remove it.
The problem is I have created a custom ValueFormatter and I can't understand where these values come from, all are wrong.
private void setData() {
for (int i = 1; i <= 10; i++) {
Entry entry = new Entry(i, i);
values.add(entry);
}
IAxisValueFormatter valueFormatter = new myValueFormatter();
XAxis xAxis = mChart.getXAxis();
xAxis.setValueFormatter(valueFormatter);
LineDataSet set1 = new LineDataSet(values, "DataSet 1");
ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
dataSets.add(set1); // add the datasets
// create a data object with the datasets
LineData data = new LineData(dataSets);
// set data
mChart.setData(data);
}
custom formatter class:
I have an array which has 1,2,3,4,5,6,7,8,9,10 values
but I get 2,4,6,8,10 values in getFormattedValue method.
public classmyValueFormatter implements IAxisValueFormatter {
#Override
public String getFormattedValue(float value, AxisBase axis) {
System.out.println(value); //Here I get odd values where they come from I don't know.
}
}
Well, generally that's how library is written. Have a look here:
https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java#L205
String label = mXAxis.getValueFormatter().getFormattedValue(mXAxis.mEntries[i / 2], mXAxis);
Author's intention was probably to give more spacing between labels. If you think this is a bug, submit issue to library's repository on Github.

Drawing horizontal bar chart with `MPAndroidChart`

Does anybody have an idea on how to make this: my app image look like this: how it should be?
My question is: how to make each line of the Horizontal Bar Chart fill between the two lines?
for (Iterator<Map.Entry<String, Float>> iterator = structuredData.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<String, Float> entry = iterator.next();
//i*10 => starting position of the bar
horizontalBarChartArr.add(new BarEntry((i*10), entry.getValue()));
names.add(entry.getKey());
i++;
}
XAxis xAxis = horizontalBarChart.getXAxis();
xAxis.setValueFormatter(new IAxisValueFormatter() {
#Override
public String getFormattedValue(float value, AxisBase axis) {
return names.get((int)value % names.size());
}
});
xAxis.setDrawGridLines(true);
xAxis.setDrawAxisLine(true);
BarDataSet barDataSet = new BarDataSet(horizontalBarChartArr, "Day Expenses");
barDataSet.setColors(Color.RED);
BarData data = new BarData(barDataSet);
data.setBarWidth(9f);
horizontalBarChart.setDoubleTapToZoomEnabled(false);
Description a = new Description();
a.setText("");
horizontalBarChart.setDescription(a);
horizontalBarChart.invalidate();
horizontalBarChart.animateY(1200);
horizontalBarChart.setData(data);
Check this example to your case:
https://github.com/ddanny/achartengine
It´s Automatically exported from code.google.com/p/achartengine

How to add real time data in Barchart using MPAndroidChart library

I am using MPAndroid Chart library to draw BarChart.
But not getting how to draw bars with real time data in on button click.
Can anyone please help me in this.
Thanks.
After getting data store that in List(graphData). Then,
BarChart barChart;
/*List to store real time data*/
private List<Integer> graphData = new ArrayList<>();
/*List of String which contains X-axis values */
ArrayList<String> xAxisValuesList = new ArrayList<>();
// create BarEntry for group
ArrayList<BarEntry> group = new ArrayList<>();
for (int i = 0; i < graphData.size(); i++) {
Log.d(TAG, "generating for:" + graphData.get(i));
group.add(new BarEntry(graphData.get(i), i));
}
// creating dataset for group
BarDataSet barDataSet = new BarDataSet(group, "Label");
// combined all dataset into an arraylist
ArrayList<BarDataSet> dataSets = new ArrayList<>();
dataSets.add(barDataSet);
// initialize the Bardata with argument labels and dataSet
BarData barData = new BarData(xAxisValuesList, dataSets);
barChart.setData(barData);

MPAndroidChart adding and display bar chart label

Just started using the MPAndroidChart version 3.0.0 beta and i have created a project that can show my values in a bar chart. My question is where do i add and display labels.
Each Bar should have its own label eg. "Flue", "Cheese" etc at the bottom. Not sure what function does this, am actively searching and reading the Docs/Wiki but no joy currently.
Depending on your preferences, you can use the data property of an Entry to store the label and then return it in your IAxisValueFormatter implementation:
public class LabelValueFormatter implements IAxisValueFormatter {
private final DataSet mData;
public LabelValueFormatter(DataSet data) {
mData = data;
}
#Override
public String getFormattedValue(float value, AxisBase axis) {
// return the entry's data which represents the label
return (String) mData.getEntryForXPos(value, DataSet.Rounding.CLOSEST).getData();
}
}
This approach allows you to use the Entry constructor (or BarEntry in this case) to add the labels, which can improve the readability of your code:
ArrayList<BarEntry> entries = new ArrayList<>();
for (int i = 0; i < length; i++) {
// retrieve x-value, y-value and label
entries.add(new BarEntry(x, y, label));
}
BarDataSet dataSet = new BarDataSet(entries, "description");
BarData data = new BarData(dataSet);
mBarChart.setData(data);
mBarChart.getXAxis().setValueFormatter(new LabelValueFormatter(data));
Also check out this answer for more information and an alternative approach on using labels with the BarChart and the new 3.0.0 version of the library.

MPAndroidChart is not animated when calling notifyDataSetChanged()

Is there supposed to be animation when I have an updated set of data values, and then updating the chart with them values and calling chart.notifyDataSetChanged in MPAndroidChart?
I would assume the effect would be similar to the bar growing in length or reducing in length accordingly, but it simply just snaps to the value.
Code:
if (m_chartHourlySales.getData() != null &&
m_chartHourlySales.getData().getDataSetCount() > 0)
{
set1 = (BarDataSet)m_chartHourlySales.getData().getDataSetByIndex(0);
set1.setValues(values.value);
m_chartHourlySales.getData().notifyDataChanged();
m_chartHourlySales.notifyDataSetChanged();
} else {
set1 = new BarDataSet(values.value, getResources().getString(R.string.total_sales_figures_for_each_hour));
set1.setValueFormatter(new ValueFormatter() {
#Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler)
{
return NumberFormat.getCurrencyInstance(Locale.getDefault()).format(value);
}
});
set1.setValueTextColor(Color.WHITE);
ArrayList<IBarDataSet> dataSets = new ArrayList<>();
dataSets.add(set1);
BarData data = new BarData(dataSets);
data.setValueTextSize(10f);
data.setBarWidth(barWidth.value);
m_chartHourlySales.moveViewToX(0);
m_chartHourlySales.setData(data);
m_chartHourlySales.setVisibleXRangeMaximum(17*20);
m_chartHourlySales.setVisibleXRangeMinimum(17*6);
m_chartHourlySales.moveViewToX(0);
}
m_chartHourlySales.invalidate();
m_chartHourlySales.refreshDrawableState();

Categories

Resources