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.
Related
I need to get all bars but I am getting single bar (last array).Even the logic is right.I don't know please help me.Thanks in advance.I search in google but I didn't got answer.
Below is main part of full code
Initialize
String empName[];
int converted[], notconverted[], notcontacted[];
Here I made Json parsing the data coming from the server
for (int i = 0; i < employees_array.length(); i++) {
empName = new String[employees_array.length()];
converted = new int[employees_array.length()];
notconverted = new int[employees_array.length()];
notcontacted = new int[employees_array.length()];
JSONObject empData = employees_array.getJSONObject(i);
empName[i] = empData.getString("EmployeeName");
empName[i].replace("-?\\d+.\\d+", " ");
if (empData.has("ConvertedActionCount")) {
converted[i] = employees_array.getJSONObject(i).getInt("ConvertedActionCount");
}
if (empData.has("NotConvertedActionCount")) {
notconverted[i] = employees_array.getJSONObject(i).getInt("NotConvertedActionCount");
}
if (empData.has("NotContactedActionCount")) {
notcontacted[i] = employees_array.getJSONObject(i).getInt("NotContactedActionCount");
}
Log.d("arraysize", converted[i] + "");
function_EMPChart(empArraysize, empName, converted,
notconverted, notcontacted);
I am passing values to function Emp chart method
private void function_EMPChart(int empArraysize, String[] s, int[]
converted, int[] notconverted, int[] notcontacted) {
XAxis xl = msc_managerDashboard_empStats.getXAxis();
xl.setPosition(XAxis.XAxisPosition.BOTTOM);
xl.setDrawAxisLine(true);
xl.setDrawGridLines(false);
xl.setGranularity(10f);
YAxis yl = msc_managerDashboard_empStats.getAxisLeft();
yl.setDrawAxisLine(true);
yl.setDrawGridLines(true);
yl.setAxisMinimum(0f); // this replaces setStartAtZero(true)
YAxis yr = msc_managerDashboard_empStats.getAxisRight();
yr.setDrawAxisLine(true);
yr.setDrawGridLines(false);
yr.setAxisMinimum(0f);
ArrayList<BarEntry> yVals = new ArrayList<BarEntry>();
ArrayList<String> xVals = new ArrayList<>();
xVals = new ArrayList<String>(Arrays.asList(s));
msc_managerDashboard_empStats.setFitBars(true);
for (int j = 0; j < s.length; j++) {
Log.d("checklength", j + "");
int value1 = converted[j];
int value2 = notconverted[j];
int value3 = notcontacted[j];
Log.d("getvalue", value1 + " " + value2 + " " + value3);
yVals.add(new BarEntry(j, new float[]{value1, value2, value3}));
yVals.add(new BarEntry(4, new float[]{10.0f, 20.0f, 30.0f}));
yVals.add(new BarEntry(5, new float[]{5.0f, 15.0f, 20.0f}));
Log.d("checky", yVals.add(new BarEntry(j, new float[]{converted[j], notconverted[j], notcontacted[j]})) + "");
}
BarDataSet set1 = new BarDataSet(yVals, "");
set1.setColors(getColors());
ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>();
dataSets.add(set1);
BarData data = new BarData(dataSets);
data.notifyDataChanged();
msc_managerDashboard_empStats.setData(data);
msc_managerDashboard_empStats.notifyDataSetChanged();
msc_managerDashboard_empStats.invalidate();
Log.d("yvalues", yVals + "");
msc_managerDashboard_empStats.setFitBars(true);
}
I guess you are using this library.
I don't really understand your code in what you try to accomplish (I see multiple bars per employee I guess).
At least what is wrong, you call setData within this for loop for (int i = 0; i < employees_array.length(); i++), which means you override the data every time.
You should create a list of BarDataSets in that for loop and set the data in the end.
Your main issue here is that you create a new set of data every time. If you keep the same set your code might also work. Define dataSets once in the beginning and keep adding your sets. I mean this line:
ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>();
dataSets.add(set1);
I guess you want to have a grouped bar chart which you can find here: https://github.com/PhilJay/MPAndroidChart/wiki/Setting-Data#grouped-barchart
Example:
YourData[] group1 = ...;
YourData[] group2 = ...;
List<BarEntry> entriesGroup1 = new ArrayList<>();
List<BarEntry> entriesGroup2 = new ArrayList<>();
// fill the lists
for(int i = 0; i < group1.length; i++) {
entriesGroup1.add(new BarEntry(i, group1.getValue()));
entriesGroup2.add(new BarEntry(i, group2.getValue()));
}
BarDataSet set1 = new BarDataSet(entriesGroup1, "Group 1");
BarDataSet set2 = new BarDataSet(entriesGroup2, "Group 2");
BarData data = new BarData(set1, set2);
data.setBarWidth(barWidth); // set the width of each bar
barChart.setData(data);
barChart.groupBars(1980f, groupSpace, barSpace); // perform the "explicit" grouping
barChart.invalidate(); // refresh
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();
In my android application, I am new to graphs and using MPchart library to draw the graphs. I'm displaying the graph using string array on both - X axis and Y axis.
For x axis I created it successfully but for Y axis I need to convert my ArrayList<String> to BarData array list. I don't know how to do convert it. Can anyone tell me how to achieve this?
For X axis:
private ArrayList<String> getXAxis() {
ArrayList<String> xAxis = new ArrayList<>();
xAxis = new ArrayList<String>(Arrays.asList(bar_graph_names)); //converting string to arraylist
return xAxis;
}
For Y axis plotting values:
private ArrayList<BarDataSet> getData() {
ArrayList<String> yAxis_conv = new ArrayList<>();
yAxis_conv = new ArrayList<String>(Arrays.asList(bar_graph_values));
ArrayList<BarDataSet> yAxis_Datasets=null;
ArrayList<BarEntry> yAxis = new ArrayList<>();
for(int i = 0; i < bar_graph_values.length; i++)
{
BarEntry [] barentry = new BarEntry[bar_graph_values.length];
barentry[i] = new BarEntry(Float.valueOf(yAxis_conv.get(i)),i);
}
BarDataSet barDataSet1 = new BarDataSet(yAxis_conv , "");//Error occurring line
barDataSet1.setColors(ColorTemplate.COLORFUL_COLORS);
yAxis_Datasets = new ArrayList<>();
yAxis_Datasets.add(barDataSet1);
return yAxis_Datasets;
}
BarData object (which you give to the chart View) consist of one List representing x-values and one or more BarDataSet objects representing y-values data. BarDataSet object has String name and List of y-values.
Your structure of this objects is simply wrong. (for starters yAxis_conv is List<String>, where BarDataSet requires List<BarEntry>). There's more mistakes, but i'm not gonna point them out, just have some working code below:
private void setData() {
ArrayList<String> xVals = new ArrayList<String>();
ArrayList<BarEntry> yVals = new ArrayList<BarEntry>();
xVals = new ArrayList<String>(Arrays.asList(bar_graph_names));
for(int i=0; i < bar_graph_values.length; i++) {
BarEntry entry = new BarEntry(Float.valueOf(bar_graph_values[i]), i);
yVals.add(entry);
}
BarDataSet newSet = new BarDataSet(yVals, "DataSet");
BarData data = new BarData(xVals, newSet);
mChart.setData(data);
}
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.
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.