I am using MPAndroidChart to generate a simple bar chart, inside a collapsing toolbar. When I add entries, the value of the entry is visible at the correct height on the chart, but I can't see the bar.
This is how I create my variables:
final List<BarEntry> barEntries = new ArrayList<>();
final BarDataSet barDataSet = new BarDataSet(barEntries, getResources().getString(R.string.cycles_profiled));
final BarData barData = new BarData(barDataSet);
This is how I populate the data and refresh the chart:
final Calendar cal = getFirstDayOfWeek();
for (int i = 0; i < NUMBER_OF_DAYS; i++) {
long date = cal.getTimeInMillis();
barEntries.add(new BarEntry(date, map.get(date)));
cal.add(Calendar.DAY_OF_WEEK, 1);
}
barDataSet.setValues(barEntries);
barChart.setData(barData);
barData.notifyDataChanged();
barChart.notifyDataSetChanged();
barChart.invalidate();
I have no problem creating bar charts in other parts of my app. When I draw linecharts inside the collapsing toolbar, it also works fine.
Had the same issue, solved it thanks to OumaSyuu.
For some reason the BarChart has a difficulty with milliseconds.. convert your milliseconds to minutes: TimeUnit.MILLISECONDS.toMinutes(millisecondValue) and your life will be honey!
If converting to minutes doesn't help try to a different (higher) time unit. The time unit that will be good for you is the average gap between the bars, for me it was hours.
Another interesting point that may help you style the chart - In the method setBarWidth(float mBarWidth), the input mBarWidth represent values not pixels.
i was facing the same issue when i used timestamp for X axis values which was reported as a bug in the library, so i came out with the following solution
first create an arraylist:
ArrayList<String> xAxis_stringArray = new ArrayList<>();
and then while you add the entries to the entry list, set the x value to be the index of the data source (string value) and add the string value to the string array like that:
jsonObject = results.getJSONObject(index);
String s = jsonObject.getString(x);
xAxis_stringArray.add(s);
entries.add(new Entry(Float.valueOf(index), Float.valueOf(jsonObject.getString(y))));
and finally refer the xAxis to the value formatter class:
XAxis xAxis = sum_chart.getXAxis();
xAxis.setValueFormatter(new TimeAxisValueFormatter(xAxis_stringArray));
TimeAxisValueFormatter class:
public class TimeAxisValueFormatter implements IAxisValueFormatter {
ArrayList<String> arrayList = new ArrayList<>();
public TimeAxisValueFormatter(ArrayList<String> list) {
this.arrayList = list;
}
#Override
public String getFormattedValue(float value, AxisBase axis) {
return arrayList.get(Math.round(value));
}}
You are missing to set .setColor
Try with
barDataSet.setColor(Color.rgb(0, 155, 0)); //Put your RGB Color
I had the same problem just now, for me increasing the barwidth solved the problem. I think the problem lays with how spread out your data is which impacts the width of the lines. If you have a dataset that is only spread out over an hour and has entry for every minute of that hour, I think this problem won't exist. But if you are like me and have sparse data over 5 hours or so, then the barwidth just become smaller and smaller to accommodate all those entries and the bar just disappears.
Example:
data.setBarWidth(2f);
When I increased the barwidth to 80f:
data.setBarWidth(80f);
Related
I have made pie charts using mp-android chart.I have placed 9 charts in a grid but there is extra spaces between them.I need to remove those necessary spaces and make the edges touch each other.
This is the java method which inflates each piechart,I have tried the previous answers but nothing works.
static void makePie(PieChart pieChart, int type, boolean spin, Context con){
pieChart.setExtraOffsets(-30, -30, -30, -30);
ArrayList<PieEntry> yvalues = new ArrayList<>();
for(int i=0;i<type;i++){
yvalues.add(new PieEntry(10F, ""));
}
PieDataSet dataSet = new PieDataSet(yvalues, "Net Worth");
ArrayList<String> xVals = new ArrayList<String>();
PieData data = new PieData(dataSet);
pieChart.setCenterTextColor(Color.BLACK);
pieChart.setData(data);
pieChart.setDrawHoleEnabled(false);
final int[] MY_COLORS = {
Color.rgb(246,230,196),
Color.rgb(200,237,253),
Color.rgb(252,199,202),
Color.rgb(179,233,216),
Color.rgb(247,233,174),
Color.rgb(211,211,246),
Color.rgb(108,59,57),
Color.rgb(75,132,138),
Color.rgb(124,96,66),
Color.rgb(247,173,89),
Color.rgb(235,108,63),
Color.rgb(208,75,52),
Color.rgb(255,202,39),
Color.rgb(147,37,166),
Color.rgb(22,158,250),
Color.rgb(118,7,47),
Color.rgb(44,183,80),
Color.rgb(100,22,151),
Color.rgb(88,42,71),
Color.rgb(27,40,121),
Color.rgb(29,112,74),
Color.rgb(252,216,82),
Color.rgb(247,99,64),
Color.rgb(232,57,52)
};
ArrayList<Integer> colors = new ArrayList<Integer>();
dataSet.setColors(colors);
for(int i=0;i<type;i++){
colors.add(getRandom(MY_COLORS));
}
List<LegendEntry> entries = new ArrayList<>();
dataSet.setDrawValues(false);
data.setValueTextSize(16f);
data.setValueTextColor(Color.DKGRAY);
pieChart.getDescription().setEnabled(false);
pieChart.setTransparentCircleAlpha(0);
pieChart.getLegend().setEnabled(false);
pieChart.setRotationEnabled(false);
pieChart.setClickable(false);
pieChart.setTouchEnabled(false);
pieChart.setExtraOffsets(-10,0,-10,0);
pieChart.invalidate();
if(spin){
Animation animation = AnimationUtils.loadAnimation(con, R.anim.rotate);
pieChart.startAnimation(animation);
}
}
https://drive.google.com/open?id=1mIPMjFW3BlWhWLfQWIV65sfx9FO091pv
This is the output, there are spaces between the grids, which is taking too much space, andneeded to be removed so that the piecharts touch each other,
I've tried my self then I changed the setExtraOffsets in your code
it had an effect on the padding of your view but the shape was not circled any more
I recommend to remove setExtraOffsets in your code and see the result.
mention that you are using setExtraOffsets two parts of your code
I´m working with MPAndroid charts on my app to draw a chart from my sqlite database using "weight" values for the Y axes and "date" values for the X axes.
The problem is that just some rows of my database have that weight value. When all the rows have the weight layout my code works like a charm, but when there is a row that doesn´t have weight value, and the next one contains that weight value, it leaves a space on the YAxes of the chart, altought the date value is set on XAxes. As a result of that, a value is missed on Y Axes for every row without the weight value, because the value that comes after the weight row is moved one point forward. For example:
I have this code for setting up the chart:
public void setUpCharts(){
chart = (LineChart) rootView.findViewById(R.id.weightChart);
chart.setNoDataTextDescription("Nothing");
chart.setDrawBorders(false);
chart.setDescription("");
chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);
chart.getAxisRight().setEnabled(false);
chart.getAxisLeft().setEnabled(false);
chart.getAxisLeft().setDrawGridLines(false);
chart.getAxisRight().setDrawGridLines(false);
chart.getXAxis().setDrawGridLines(false);
chart.getXAxis().setDrawAxisLine(false);
chart.getLegend().setEnabled(false);
chart.setScaleEnabled(false);
chart.setPinchZoom(false);
chart.setDoubleTapToZoomEnabled(false);
weights = new ArrayList<>(); //Pesos
dates = new ArrayList<String>(); //Días del mes
getChartData();
LineDataSet dataSet = new LineDataSet(weights, "Weights");
dataSet.setDrawCubic(false);
dataSet.setCircleRadius(4);
dataSet.setLineWidth(3);
dataSet.setDrawValues(true);
dataSet.setColor(getContext().getResources().getColor(R.color.colorWeightChart));
dataSet.setCircleColor(getContext().getResources().getColor(R.color.colorWeightChart));
dataSet.setCircleColorHole(getContext().getResources().getColor(R.color.colorWeightChart));
LineData data = new LineData(dates, dataSet);
chart.setData(data);
//LimitLine
String weight_get = PreferenceManager.getDefaultSharedPreferences(getContext()).getString("Goal_weight", null);
if(!weight_get.equals(null) && !weight_get.equals("")){
float weight_goal = Float.valueOf(weight_get);
YAxis leftAxis = chart.getAxisLeft();
LimitLine ll = new LimitLine(weight_goal);
ll.setLineColor(getContext().getResources().getColor(R.color.weightTabFAB));
ll.setLineWidth(1f);
ll.enableDashedLine(10f, 10f, 0f);
leftAxis.addLimitLine(ll);
float YMax= dataSet.getYMax();
if(weight_goal > YMax){
float difference = weight_goal - YMax;
chart.getAxisRight().setAxisMaxValue(weight_goal + difference); //So the limit line will be always visible
chart.getAxisLeft().setAxisMaxValue(weight_goal + difference);
}
}
chart.setVisibleXRangeMaximum(5f);
}
And I use getChartData to set up all the chart data getting the values from my sqlite database. It´s supposed to add just the values of rows in which weight exists, and in fact the log shows that it works correctly, so I don´t know how can I fix it.
protected void getChartData(){
IDs = new ArrayList<Integer>();
Cursor data = dataSource.getAllItems();
if(data!=null) {
while(data.moveToNext()){
int id = data.getInt(data.getColumnIndex(RecordsDataSource.ColumnRecords.ID_RECORDS));
String weight= data.getString(data.getColumnIndex(RecordsDataSource.ColumnRecords.WEIGHTS_RECORDS));
if(weight!=null && !weight.equals("")){
long milisDate =data.getLong(data.getColumnIndex(RecordsDataSource.ColumnRecords.DATES_RECORDS));
String date = Utils.milisToDate(milisDate, "dd/MM");
IDs.add(id);
weights.add(new Entry(Float.valueOf(weight), id -1));
dates.add(date);
Log.i("ID "+ String.valueOf(id),"Not null, "+ weight);
}else{
Log.i("ID "+ String.valueOf(id), "Null");
}
}
data.close();
}
}
I have been all the day trying to solve this issue, but nothing has worked.
Could somebody help me please?
By the way, sorry for my bad English.
The problem is in your id in getChartData() method. The id is skipping your chart Entry position.
Instead of this
weights.add(new Entry(Float.valueOf(weight), -1));
Add a variable for entry index and increment it on each iteration
index++;
weights.add(new Entry(Float.valueOf(weight), index));
It should work.
I am using mpandroidchart and I want to draw a circle only for one Entry in the LineDataSet but not the rest. I have tried to accomplish it using two LineDataSets but it hasn't worked so far. Here's my code:
LineDataSet scoreDataSet = new LineDataSet(values, "Score");
scoreDataSet.setDrawCircles(false);
// Entry with max value is the last one
Entry circleEntry = scoreDataSet.getEntryForXIndex(scoreDataSet.getEntryCount()-1);
LineDataSet circularDataSet = new LineDataSet(values, "Score");
circularDataSet.setDrawCircles(true);
int size = circularDataSet.getEntryCount()-1;
for (int i=0; i<size; i++) {
if (i != circleEntry.getXIndex()) {
circularDataSet.removeEntry(circularDataSet.getEntryForXIndex(i));
}
}
.
.
.
ArrayList<LineDataSet> dataSets = new ArrayList<LineDataSet>();
dataSets.add(scoreDataSet);
dataSets.add(circularDataSet);
This just prints a dot(circularDataSet) and not the scoreDataSet. I was expecting it to merge both the DataSets so as to mark the highest value with a circle and drawing the rest as a line chart.
Your approach looks good in general, there are just a few flaws.
Don't create the "circularDataSet" and initialize it with the same values like the "scoreDataSet" and then remove all except one.
What you should do instead is find the largest entry in your "scoreDataSet", and then only add this single entry to the "circularDataSet".
I'm using MPChartlib for a basic "Barchart" (3 bars and values between 0 and 100).
the background of the app is dark so I'd like to put the text in white but when I set the text with color code "FFFFFF" in chart_color stored in string.xml but the text appear in dark blue.
//Axe X
XAxis x = barchart.getXAxis();
x.setPosition(XAxisPosition.BOTTOM);
x.setTextColor(R.color.chart_color);
x.setAxisLineColor(R.color.chart_color);
// Design
barchart.setDragEnabled(false);
barchart.setDrawGridBackground(false);
barchart.setTouchEnabled(false);
barchart.setHighlightEnabled(false);
barchart.setMaxVisibleValueCount(101);
barchart.setDescription(null);
barchart.setGridBackgroundColor(R.color.chart_color);
barchart.invalidate(); // refresh
//Axe Y
barchart.getAxisLeft().setAxisMaxValue(100);
barchart.getAxisLeft().setDrawTopYLabelEntry(true);
barchart.getAxisLeft().setDrawAxisLine(false);
barchart.getAxisLeft().setDrawGridLines(false);
barchart.getAxisLeft().setAxisLineColor(R.color.chart_color);
barchart.getAxisLeft().setTextColor(R.color.chart_color);
barchart.getAxisRight().setAxisMaxValue(100);
barchart.getAxisRight().setDrawTopYLabelEntry(true);
barchart.getAxisRight().setAxisLineColor(R.color.chart_color);
barchart.getAxisRight().setTextColor(R.color.chart_color);
I tried lots of things and research but couldn't find the issue, does the lib doesn't use the same kind of color code or something ?
Thanks for your help,
Alex
You are passing the resource id to the library, not the actual color.
Use this to get the color:
int color = ContextCompat.getColor(context, R.color.chart_color);
LineDataSet dataSet = ...;
dataSet.setColor(color);
You can also find this in the documentation.
if you want change bars color prefer pass context as well like example below
ArrayList<BarEntry> entries = new ArrayList<>();
entries.add(new BarEntry(87f, 0));
entries.add(new BarEntry(90f, 1));
ArrayList<String> labels = new ArrayList<>();
labels.add("title 1");
labels.add("title 2);
BarDataSet dataSet = new BarDataSet(entries, "# of Calls ");
BarData barData = new BarData(labels, dataSet);
dataSet.setColors(new int[]{R.color.color1 , R.color.color2} , context);
barChart.setData(barData);
barChart.animateY(3000 , Easing.EasingOption.EaseOutBack );
Is their any possibility to hide all rounded items from this picture.
I have used the following code,
public void setDataList(List<HorizontalBarChartData> dataList, Resources resources) {
ArrayList<String> categories = new ArrayList<String>();
ArrayList<BarEntry> values = new ArrayList<BarEntry>();
ArrayList<BarDataSet> dataSets = new ArrayList<BarDataSet>();
BarDataSet set1;
for (int i = 0; i < dataList.size(); i++) {
categories.add(dataList.get(i).getName());
values.add(new BarEntry(dataList.get(i).getValue(), i));
}
/*set1 = new BarDataSet(values, "Income, Expense, Disposable Income");*/
set1 = new BarDataSet(values, "Category 1, Category 2, Category 3");
set1.setBarSpacePercent(35f);
set1.setColors(new int[]{resources.getColor(R.color.cyan_blue), resources.getColor(R.color.vermilion_tint), resources.getColor(R.color.sea_green)});
dataSets.add(set1);
BarData data = new BarData(categories, dataSets);
data.setValueTextSize(10f);
horizontalBarChart.setData(data);
}
Update
How to hide rounded part from this image?
Yes, is possible, just using following code:
mChart.setDescription(""); // Hide the description
mChart.getAxisLeft().setDrawLabels(false);
mChart.getAxisRight().setDrawLabels(false);
mChart.getXAxis().setDrawLabels(false);
mChart.getLegend().setEnabled(false); // Hide the legend
As per this answer
mChart.getXAxis().setDrawLabels(false); will hide the entire X-Axis(as required for this question).
For positioning the X-Axis, following code works.
XAxis xAxis = mChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
Position can be set to
BOTTOM
BOTH_SIDED
BOTTOM_INSIDE
TOP
TOP_INSIDE
This helps if you are trying to hide only the particular side axis instead of hiding the entire axis.
It appears mChart.setDescription() no longer accepts a String.
The method now accepts an instance of the Description Class like this:
mChart.setDescription(Description description)
So to modify or delete the Chart Description you may do it like below
Description description = new Description();
description.setText("");
mChart.setDescription(description);
Following code work for all chart
Legend l = mchart.getLegend();
l.setEnabled(false);.
To hide description, use this
mChart.getDescription().setEnabled(false)
Below code works for PieChart. Try to get same method for your Chart.
Legend l = mChart.getLegend();
l.setPosition(LegendPosition.NONE);
chart=(LineChart) findViewById(R.id.Chart);
chart.getLegend().setEnabled(false); // for hiding square on below graph
Kotlin solution for MPAndroidChart:v3.1.0
chart.description.isEnabled = false // hide the description
chart.legend.isEnabled = false // hide the legend
chart.xAxis.setDrawLabels(false) // hide bottom label
chart.axisLeft.setDrawLabels(false) // hide left label
chart.axisRight.setDrawLabels(false) // hide right label
I had the problem, that the bottom xAxis Labels are cutted off when I used mChart.getLegend().setEnabled(false)
Now I use chart.getLegend().setForm(Legend.LegendForm.NONE); instead and the labels are not cutted of anymore