MPAndroidChart removing data set issue - android

I have implemented to simple methods:
#Override
protected void addDataSet(int day) {
LineData lineData = this.lineChart.getData();
if(lineData != null) {
ArrayList<Entry> yValues = new ArrayList<Entry>();
for(int i = 0; i < this.measureDataListEntries.size(); i++) {
String stringValue = this.measureDataListEntries.get(i).getValue();
int dayOfWeek = Helper.getDayOfWeek(this.measureDataListEntries.get(i).getTime());
float value = Float.parseFloat(stringValue);
if(dayOfWeek == day) {
yValues.add(new Entry(value, i));
}
}
String label = this.getLabel(day);
int color = this.getColor(day);
LineDataSet lineDataSet = new LineDataSet(yValues, label);
lineDataSet.setColor(color);
lineDataSet.setCircleColor(color);
lineDataSet.setLineWidth(1f);
lineDataSet.setCircleSize(4f);
lineDataSet.setFillAlpha(65);
lineData.addDataSet(lineDataSet);
this.lineChart.notifyDataSetChanged();
this.lineChart.invalidate();
this.lineChart.animateX(1000);
if(yValues.size() > 0) {
this.getCheckBox(day).setEnabled(true);
}
}
}
#Override
protected void removeDataSet(int day) {
LineData lineData = this.lineChart.getData();
if(lineData != null) {
String label = this.getLabel(day);
lineData.removeDataSet(lineData.getDataSetByLabel(label, true));
this.lineChart.notifyDataSetChanged();
this.lineChart.invalidate();
this.lineChart.animateX(1000);
}
}
At startup i add seven different datasets: monday, tuesday, wednesday, thursday, friday, saturday, sunday. The adding and removing of datasets works for all days except the day at the first position of the dataset in this case it is monday. the remove method gets called correctly but the dataset does not get removed. adding works always.
Only the dataset at first position cant be removed
Is there a workaround?
EDIT
The code used for the deletion from MPAndroidChart is the following:
public T getDataSetByLabel(String label, boolean ignorecase) {
int index = getDataSetIndexByLabel(mDataSets, label, ignorecase);
if (index <= 0 || index >= mDataSets.size())
return null;
else
return mDataSets.get(index);
}
why there is <= 0 and not just < 0?
Ofcourse adding a dummy dataset at the first position would make it working but im never a friend of such ugly codings. Why dont accept index = 0 for deliting?

This is already fixed. Use the latest version of the library.
Refer this: https://github.com/PhilJay/MPAndroidChart/issues/255
Fixed since 16th December, 2014.

Related

MPAndroid BarChart duplicate values displayed

I've used the BarChart provided by MPAndroidChart library to display a bar graph.
When there is data for more than one values on the x-axis (in this case the date), the output is shown as expected. However, when there is data for only a single date, for some reason that date is displayed twice on the x-axis.
I would like to prevent one of the values from being displayed. Below is the code that is displayed the results in the image.
private void showBarGraph(List<Object> response) {
barChart.setNoDataText(getResources().getString(R.string.sorry_data_not_available));
barChart.clear();
if(response.size()>0) {
int highestValue = response != null && response.size() > 0 ? response.size() : 0;
barChart.getAxisLeft().setAxisMaximum(highestValue);
barChart.getAxisLeft().setAxisMinimum(0);
barChart.animateY(1000);
List<BarEntry> entries = new ArrayList<>();
List<String> xAxisValues = new ArrayList<>();
if (response != null) {
for (int i = 0; i < respones.size(); i++) {
entries.add(new BarEntry(i, response.get(i).getCount(), ContextCompat.getColor(getActivity(), R.color.graph)));
xAxisValues.add(response.get(i).getTimekey());
}
barChart.getAxisLeft().setLabelCount(highestValue > 10 ? 10 : highestValue, false);
barChart.getXAxis().setLabelCount(response.size() <= 12 ? response.size() : 12, false);
if (response.size() >= 4) {
barChart.getXAxis().setLabelRotationAngle(-45);
} else {
barChart.getXAxis().setLabelRotationAngle(0);
}
}
IndexAxisValueFormatter xAxisValueFormatter = new IndexAxisValueFormatter(xAxisValues);
barChart.getXAxis().setValueFormatter(xAxisValueFormatter);
BarXYMarkerView xymv = new BarXYMarkerView(getActivity(), xAxisValueFormatter);
// Set the marker to the chart
xymv.setChartView(barChart);
barChart.setMarker(xymv);
BarDataSet set = new BarDataSet(entries, null);
set.setDrawValues(false);
List<Integer> graphColors = new ArrayList<>();
graphColors.add(ContextCompat.getColor(getActivity(), R.color.graph));
set.setColors(graphColors);
BarData data = new BarData(set);
barChart.setData(data);
barChart.invalidate();
}
}
The code is good for data with entries on multiple dates. Can someone guide me on how I can prevent the duplicate date value when there is data for only one date.

How can I create a group of months in expandable list view?

How can I create a group of months and add days to each of them in expandable list view? I try with for loop like this
private void prepareListData() {
months = new ArrayList<String>();
days= new HashMap<String, List<String>>();
daysArray = new ArrayList<String>();
Calendar currentDate = Calendar.getInstance();
for (int i = 50; i >= 0; i--) {
String a = MyChangeDateFomatter.getStringDateFormatMonth(currentDate
.getTimeInMillis());
currentDate.add(Calendar.DATE, -1);
if(months==null||(months.get(i).equalsIgnoreCase(months.get(i-1))==false)) {
months.add(a);
for (int j = 50; i >= 0; i--) {
if(months.get(i).equalsIgnoreCase(months.get(i-1))==true) {
String b = MyChangeDateFomatter.getStringDateFormatMonth(currentDate
.getTimeInMillis());
daysArray.add(b);
days.put(months.get(i),daysArray);
}
else {
days.put(months.get(i-1),daysArray);
}
}
}
}
}
error
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.testexpandablelistview/com.example.testexpandablelistview.CalendarActivity}:
java.lang.IndexOutOfBoundsException: Invalid index 50, size is 0
Please show me how to do that?
The reason why you are getting an IndexOutOfBoundsException is because you are trying to get an item at position 50 of your months list in your first if statment while the list had no members.
The following code should give you the correct months List and days Hash. (I haven't tested it though, so there could be some errors.)
String a = MyChangeDateFomatter.getStringDateFormatMonth(currentDate
.getTimeInMillis());
months.add(a);
daysArray.add(a);
// Removed one since it was added outside the loop
for (int i = 49; i >= 0; i--) {
currentDate.add(Calendar.DATE, -1);
a = MyChangeDateFomatter.getStringDateFormatMonth(currentDate
.getTimeInMillis());
// Checks if a is in the months List
if (!months.get(months.size() - 1).equals(a)) {
days.put(months.get(months.size() - 1), daysArray);
daysArray = new ArrayList<>();
months.add(a);
}
daysArray.add(a);
}
days.put(months.get(months.size() - 1), daysArray);

How to move Date under X axis?

I am using PhilJay/MPAndroidChart library in my app and I'd like to know if 2 things are possible:
to show the last 14 days and then scroll for previous days?
Can the dates (currently on the top of the graph) be moved to the bottom, along the x axis?
Here is the current pic from the app and where i want to move date
my method:
private void populateGraph(Cursor data) {
ArrayList<Entry> cravingsPoints = new ArrayList<Entry>();
ArrayList<Entry> severityPoints = new ArrayList<Entry>();
ArrayList<String> dates = new ArrayList<String>();
int index = 0;
for (int i = 0; i < data.getCount(); i++) {
if (i == 0) {
// if orientation changed we need to start from the first one again
data.moveToFirst();
} else {
data.moveToNext();
}
try {
String date = data.getString(data.getColumnIndex(SmokeFreeContentProvider.DIARY_DATE));
int cravings = data.getInt(data.getColumnIndex(SmokeFreeContentProvider.DIARY_CRAVINGS_COUNT));
int severity = data.getInt(data.getColumnIndex(SmokeFreeContentProvider.DIARY_CRAVINGS_SEVERITY));
DateTime diaryEntry = DateTimeFormat.forPattern("yyyyMMdd").parseDateTime(date);
String entryLabel = diaryEntry.toString("dd MMM");
cravingsPoints.add(new Entry(cravings, index));
severityPoints.add(new Entry(severity, index));
dates.add(entryLabel);
index++;
} catch (Exception e) {
Log.e("SmokeFreeCravingsGraph", e.getMessage(), e);
}
}
LineDataSet cravingsLineData = new LineDataSet(cravingsPoints, getString(R.string.cravings));
LineDataSet severityLineData = new LineDataSet(severityPoints, getString(R.string.severity));
cravingsLineData.setCircleSize(4f);
cravingsLineData.setLineWidth(6f);
cravingsLineData.setColor(getResources().getColor(R.color.green));
severityLineData.setCircleSize(4f);
severityLineData.setLineWidth(6f);
severityLineData.setColor(getResources().getColor(android.R.color.holo_blue_light));
ArrayList<LineDataSet> dataSets = new ArrayList<LineDataSet>();
dataSets.add(cravingsLineData);
dataSets.add(severityLineData);
Paint infoPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
infoPaint.setTextAlign(Paint.Align.CENTER);
infoPaint.setTextSize(com.github.mikephil.charting.utils.Utils.convertDpToPixel(14f));
infoPaint.setColor(getResources().getColor(R.color.dark_grey));
mChart.setDrawGridBackground(false);
mChart.setDrawYValues(false);
mChart.setDescription("");
mChart.setStartAtZero(true);
mChart.setPaint(infoPaint, Chart.PAINT_INFO);
mChart.setNoDataText(getString(R.string.no_cravings_info));
mChart.setNoDataTextDescription(getString(R.string.no_cravings_full_info));
mChart.setData(new LineData(dates, dataSets));
}
Yes, check the documentation: Modifying the Viewport
Take a look at the setVisibleXRange(float xRange) method.
Yes, check the documentation: XAxis
Take a look at the xAxis.setPosition(...) method.

Array Integer Logic

I have a game with progress chart and an array. I want to have a chart which the player can see its score in its last 5 games.
here's my code in my array
int[] Addition = { score1, score2, score3, score4, score5 };
if (score1 == 0) {
score1 = Game.score;
} else if (score1 != 0 && score2 == 0) {
score2 = 21;
} else if (score2 != 0 && score3 == 0) {
score3 = Game.score;
} else if (score3 != 0 && score4 == 0) {
score4 = Game.score;
} else if (score4 != 0 && score5 == 0) {
score5 = Game.score;
}
What is the problem on my logic? when it runs my first game score seems to be right. but when i play one more its just that the 1st element of the array is changing? where Am I wrong? btw please apologize my english. and I appreciate any suggestions and comments. thanks guys
:::UPDATE:::
here's my code now. Can someone check if my initialization is correct:
public class ProgressGraph extends Activity {
int[] Addition = { 0, 0, 0, 0, 0 };
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
openChart();
}
public void openChart() {
for (int i = 0; i < 5; i++) {
if (Addition[i] == 0) {
Addition[i] = Game.score;
break;
}
}
I would do something like this:
for(int i = Addition.length-1; i > 0; i--){
Addition[i] = Addition[i-1];
}
Addition[0] = Game.score;
This will mean that the most recent game will always be in position 0. If the user plays more than 5 games the oldest score gets replaced.
It also allows the user to be able to score 0.
This part of code seems to be good.
I think your score array is reset when you start the second game.
Did you try to print the scores array before the end of the second game ? Does the first score remain stored ?
Then I suggest you to use a loop like that (not tested):
for (int i = 0; i < 5; i++) {
if (score[i] == 0) {
score[i] = Game.score;
break;
}
}
Are you trying to move each old score down the list?
for (int i = 4; i > 0; i--) {
Addition[i] = Addition[i-1];
}
Addition[0] = Game.score;
In these code samples we've provided, the array values should be initialized to zero:
int[] Addition = { 0, 0, 0, 0, 0};
Taking into account your update.
- When you declare the array. The variable has a capital letter so it may have a conflict with a class. Replace Addition by addition.
With this code, if you start another activity, scores will be reset. You have to use Application extended class or SharedPreferences to save scores.

MPAndroidChart with null values

I'm using the MPAndroidChart and am really enjoying it.
A 'little' need I have is that I can put null values to the 'entrys'. I'm monitoring the apache conections on servers of my system, and I would to see if they is down (where I put the null value) or if they just no conections (0).
I tried, but the Entry class don't accept 'null' as value showing the message: 'The constructor Entry(null, int) is undefined'
Thanks!
A possible solution for you could be to check weather the object you received is null, or not. If the object is null, you don't even create an Entry object instead of just setting it's value to null.
Example:
// array that contains the information you want to display
ConnectionHolder[] connectionHolders = ...;
ArrayList<Entry> entries = new ArrayList<Entry>();
int cnt = 0;
for(ConnectionHolder ch : connectionHolders) {
if(ch != null) entries.add(new Entry(ch.getNrOfConnections(), cnt));
else {
// do nothing
}
cnt++; // always increment
}
This would create e.g. a LineChart where no circles are drawn on indices where the ConnectionHolder object was null.
For a future release of the library, I will try to add the feature so that null values are supported.
My solution is to draw another DataSet with TRANSPARENT (or arbitrary) color:
- chart with fixed number of X values
- Y values are updated periodically
- boolean flag indicate transparent part (or another color)
private static final int SERIES_SIZE = 360;
int xIndex = -1;
float xIndexVal;
private LineChart chart;
private boolean currentFlag;
public void createChart(LineDataSet dataSet) {
LineData chartData = new LineData();
prepareDataSet(dataSet);
chartData.addDataSet(dataSet);
for (int i = 0; i < SERIES_SIZE; i++) {
chartData.addXValue("" /*+ i*/);
}
chart.setData(chartData);
}
private void prepareDataSet(LineDataSet dataSet, YAxis axis, int color) {
// configure set
}
public void update(Float val, boolean flag) {
List<ILineDataSet> dsl = chart.getData().getDataSets();
Log.d("chart", String.format("%s --- %d sets, index %d", descr, dsl.size(), xIndex));
if (xIndex == SERIES_SIZE - 1) {
// remove all entries at X index 0
for (int i = 0; i < chart.getData().getDataSetCount(); i++) {
Entry entry0 = chart.getData().getDataSetByIndex(i).getEntryForIndex(0);
if (entry0 != null && entry0.getXIndex() == 0) {
chart.getData().removeEntry(entry0, i);
Log.d("chart", String.format("entry 0 removed from dataset %d, %d entries in the set", i, chart.getData().getDataSetByIndex(i).getEntryCount()));
}
else {
Log.d("chart", String.format("all %d entries in the set kept", chart.getData().getDataSetByIndex(i).getEntryCount()));
}
}
// remove empty set, if any
for (Iterator<ILineDataSet> mit = dsl.iterator(); mit.hasNext(); ) {
if (mit.next().getEntryCount() == 0) {
mit.remove();
Log.d("chart", String.format("set removed, %d sets", dsl.size()));
}
}
// move all entries by -1
for (ILineDataSet ds : dsl) {
for (Entry entry : ((LineDataSet)ds).getYVals()) {
entry.setXIndex(entry.getXIndex() - 1);
}
}
}
else {
xIndex++;
}
if (currentFlag != flag) {
currentFlag = !currentFlag;
LineDataSet set = new LineDataSet(null, "");
prepareDataSet(set, chart.getAxisLeft(), currentFlag ? Color.TRANSPARENT : Color.BLUE);
chart.getData().addDataSet(set);
if (xIndex != 0) {
chart.getData().addEntry(new Entry(xIndexVal, xIndex - 1), dsl.size() - 1);
}
}
xIndexVal = val;
chart.getData().addEntry(new Entry(val, xIndex), dsl.size() - 1);
chart.notifyDataSetChanged();
chart.invalidate();
}

Categories

Resources