I currently have 30 values in my line chart and currently the X axis is showing 01, 03, 05, 06.
How would i make it to show the X-Axis Like 01,02,03,04,05 with proper spacing between each x-axis
I'm currently using this method
float minXRange = 10;
float maxXRange = 10;
lineChart.setVisibleXRange(minXRange, maxXRange);
to show the values i want in my linechart
This works for me. You can try this. This will set the X-Axis values of the graph.
final String[] values = {"01", "02", "03"};
mChart.getXAxis().setValueFormatter(new IAxisValueFormatter() {
#Override
public String getFormattedValue(float value, AxisBase axis) {
return values[(int)value];
}
});
You may need to set the granularity of the x-axis to 1f by doing getXAxis.setGranularity(1f)
Related
I have create a simple MPAndroidChart Line Chart with values from 0 to 5.
yAxis.setAxisMinimum(0.0f);
yAxis.setAxisMaximum(5.0f);
I have added my values (0 for every point in my example)
And I also have set the formatter just to display the value:
yAxis.setValueFormatter(new IAxisValueFormatter() {
#Override
public String getFormattedValue(float value, AxisBase axis) {
return "" + value;
}
});
WHAT I EXPECTED:
To get an Y axis with values from 0 to 5 every unit (0-1-2-3-4-5)
WHAT I GOT:
Values spaced every 0.8
WHAT I TRIED:
I tried to scaled to chart till 4.8, which is a good start as it doesn't make the line "overshoot" the last line
But I still have 6 graduations instead of 5
MY QUESTION:
How is it possible to force only 5 graduations or decide the steps in these graduations...
Thanks
FULL CODE: https://pastebin.com/WWaPyNky
You have to use setGranularity:
yAxis.setAxisMinimum(0.0f);
yAxis.setAxisMaximum(5.0f);
yAxis.setGranularityEnabled(true);
yAxis.setGranularity(1.0f);
YAxis leftAxis1 = barChart.getAxisLeft();
leftAxis1.setDrawLabels(true);
leftAxis1.setDrawAxisLine(false);
leftAxis1.setDrawGridLines(true);
leftAxis1.setEnabled(true);
leftAxis1.setDrawZeroLine(true);
//leftAxis1.setTypeface(); // set a different font
leftAxis1.setTextSize(12f); // set the text size
leftAxis1.setAxisMinimum(0f); // start at zero
leftAxis1.setAxisMaximum(100f); // the axis maximum is 100
leftAxis1.setTextColor(Color.BLACK);
leftAxis1.setValueFormatter(new MyValueFormatter());
leftAxis1.setGranularity(1f); // interval 1
leftAxis1.setLabelCount(9, true);
//leftAxis1.setDrawZeroLine(true);
YAxis rightAxis1 = barChart.getAxisRight();
rightAxis1.setEnabled(false);
}
private class MyValueFormatter implements IAxisValueFormatter {
private DecimalFormat mFormat;
public MyValueFormatter() {
mFormat = new DecimalFormat("###,###,##0.0"); // use one decimal
}
#Override
public String getFormattedValue(float value, AxisBase axis) {
return mFormat.format(value) + " $"; // e.g. append a dollar-sign
}
}
}
I want to have my graph's y-axis values similar to the ones shown in the above image. How would I make it like that? There should be intervals of 10 between for the y-values. Is there any way to do this?
This should help you:
mChart.getAxisLeft().setGranularity(10);
It will make Y axis values increase by 10 and you will have desired result. Howerever, if you zoomin, the values and graph will be changed (it is normal). If you also want to disable zooming in and out you can disable it :
mChart.setScaleEnabled(false);
Hope that helps
Set
rightAxis1.setEnabled(false);
to
rightAxis1.setEnabled(true);
Right Now I am facing this issue. I am getting repeated values in xAxis the first one and the last one.And graph values are not according to the values at respective x-axis values.
and the second issue is if I want to display the values not in float but in int Rounded and change the their color to white.
ArrayList<String> xlabels = new ArrayList<String>();
xlabels.add("Jan");
xlabels.add("Feb");
xlabels.add("Mar");
xlabels.add("Apr");
xlabels.add("May");
xlabels.add("Jun");
ArrayList<String> values = new ArrayList<String>();
values.add("1");
values.add("20");
values.add("10");
values.add("80");
values.add("90");
values.add("24");
showLineChart(clickChart,xlabels,values,mColors[3]);
showLineChart Method:
private void showLineChart(LineChart chart,final List<String> xLabels, List<String> values,int color){
List<Entry> entries = new ArrayList<Entry>();
for(int i=0;i<values.size();i++){
entries.add(new Entry(i, Integer.parseInt(values.get(i))));
}
LineDataSet dataSet = new LineDataSet(entries, "Numbers");
dataSet.setLineWidth(1.75f);
dataSet.setCircleRadius(5f);
dataSet.setCircleHoleRadius(2.5f);
dataSet.setColor(Color.WHITE);
dataSet.setCircleColor(Color.WHITE);
dataSet.setHighLightColor(Color.WHITE);
dataSet.setDrawValues(true);
LineData data = new LineData(dataSet);
((LineDataSet) data.getDataSetByIndex(0)).setCircleColorHole(color);
chart.getDescription().setEnabled(false);
chart.setDrawGridBackground(false);
chart.setTouchEnabled(true);
chart.setBorderColor(Color.WHITE);
chart.setDragEnabled(true);
chart.setScaleEnabled(true);
chart.setPinchZoom(false);
chart.setBackgroundColor(color);
YAxis yAxisLeft = chart.getAxisLeft();
yAxisLeft.setTextColor(Color.WHITE);
yAxisLeft.setAxisLineColor(Color.WHITE);
YAxis yAxisRight = chart.getAxisRight();
yAxisRight.setTextColor(Color.WHITE);
yAxisRight.setAxisLineColor(Color.WHITE);
XAxis xAxis = chart.getXAxis();
xAxis.setTextColor(Color.WHITE);
xAxis.setAxisLineColor(Color.WHITE);
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setAvoidFirstLastClipping(false);
xAxis.isDrawLabelsEnabled();
xAxis.setDrawGridLines(false);
xAxis.setValueFormatter(new IAxisValueFormatter() {
#Override
public String getFormattedValue(float value, AxisBase axis) {
return xLabels.get((int)value);
}
});
chart.animateX(2500);
chart.setData(data);
chart.invalidate();
}
I was facing the same issue to resolve it add the following line:
xAxis.setGranularityEnabled(true);
Check the link for more details about Axis.
Setting granularity alone did not solve my problem. Here's what I had to do:
XAxis xAxis = chart.getXAxis();
xAxis.setGranularity(1f);
xAxis.setGranularityEnabled(true);
xAxis.setLabelCount(xLabels.size(),false); // yes, false. This is intentional
xAxis.setValueFormatter(new MyXAxisValueFormatter(xLabels));
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
And, this is my simple implementation of the IAxisValueFormatter. You may change it as per your needs:
public class MyXAxisValueFormatter implements IAxisValueFormatter {
private ArrayList<String> mValues;
MyXAxisValueFormatter(ArrayList<String> values) {
this.mValues = values;
}
#Override
public String getFormattedValue(float value, AxisBase axis) {
int index = Math.round(value);
if(index >= mValues.size()){
index = mValues.size()-1;
}
return mValues.get(index);
}
}
It's very important to know why every problem occurs and why the solution code solves the problem. So, here's the analysis part:
Why does this occur?
Even in cases where your data lies at whole number positions on the x-axis (0,1,2...), the actual label isn't necessarily placed at those specific positions. For example, the label for the data at 1.00f might be at 0.92f. (This is how the library handles it, not sure why). So, when you try to cast the float value to an int, you do not get the exact position. From the earlier example, the label at 0.92f when cast to an int would be a 0, not 1.
How does this code solve the problem?
If you understood the above section, then this must not be necessary. Anyways, here's the reasoning. From my test results, I noticed that the label position was at all times nearby the actual x. So, the Math.round() method was perfect to get the proper index out of the float value.
Additionally, I set the parameter forced as a false in the setLabelCount method because I wanted the labels to hide as the user zooms-in in the x-axis.
//set granularity to minimum value to ensure label does not give duplicate value
lineChart.getAxisLeft().setGranularity(1f);
lineChart.getXAxis().setGranularity(1f);
lineChart.getXAxis().setGranularityEnabled(true);
//also make sure you don't pass true as force parameter in below line please pass only false
bottomAxis.setLabelCount(dateLabels.size(),false);
I am using MPAndroidChart library in Android.
I'm trying to get the graph to start at the last set of x values.
I would like to show every day of the year up until now so 1 - 271 (today is the 271st day of the year)
I am using
chart.setVisibleXRangeMaximum(10)
but the chart begins by showing day 1 - 10 and I want to start by showing day 261 - 271.
According to MPAndroidChart's wiki, try
chart.moveViewToX(yourNumberOfXPoints); or chart.moveViewTo(yourNumberOfXPoints);
Why?
moveViewToX(float xValue): Moves the left side (edge) of the current
viewport to the specified x-value.
moveViewTo(float xValue, float yValue, AxisDependency axis): This will
move the left side of the current viewport to the specified x-value on
the x-axis, and center the viewport to the specified y-value on the
provided y-axis (makes sense in combination with setVisibleXRange(...)
and setVisibleYRange(...).
I think you should have to use IAxisValueFormatter
public class MyXAxisValueFormatter implements IAxisValueFormatter {
private String[] mValues;
public MyXAxisValueFormatter(String[] values) {
this.mValues = values;
}
#Override
public String getFormattedValue(float value, AxisBase axis) {
// "value" represents the position of the label on the axis (x or y)
return mValues[(int) value];
}
/** this is only needed if numbers are returned, else return 0 */
#Override
public int getDecimalDigits() { return 0; }}
In this mValues is an array which contains values which you want to set in xAxis. in your case array contains 261 - 271 values.
For more details please see : this
I want to avoid the repeated values and the -0 values in Y-Axis, avoiding the image situation.
I have these ideas to solve this, but any solution:
Limit the zoom before having repeated values in YAxis, therefore stop the infinite zoom-in on the chart
Get the YAxis values and remove the duplicate values.
Though this is an older question I'd like to add to it for future reference. Newer versions of the library have a little known feature that resolves the duplicated labels, called granularity. This is way simpler to use than the older solutions (though to be fair, this wasn't available at the time those were posted).
You can always check the latest AxisBase Javadocs (3.0.0-beta1) for a more detailed explanation. Here are the relevant methods:
setGranularity(float granularity):
Set a minimum interval for the axis when zooming in. The axis is not
allowed to go below that limit. This can be used to avoid label
duplicating when zooming in.
setGranularityEnabled(boolean enabled):
Enabled/disable granularity control on axis value intervals. If
enabled, the axis interval is not allowed to go below a certain
granularity.
So in your case you'd need to set the granularity to 0.1f since you have one decimal point. The following snippet of code should avoid the repeated values on the axis:
YAxis yAxis = mChart.getAxisLeft();
yAxis.setGranularityEnabled(true);
yAxis.setGranularity(0.1f);
tl;dr You can do this by changing the label count in onChartScale.
First, you want your listener set up:
chart.setOnChartGestureListener(this); // set a listener ;)
You try to get the top/bottom drawn values and check what gets drawn on the screen. Apply some basic calculations, and you're set.
The following code will draw 2 labels if the zoom level gets (too) high and up to 9 otherwise:
#Override
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
final YAxis yAxis = mChart.getAxisLeft();
final Transformer transformer = mChart.getTransformer(YAxis.AxisDependency.LEFT);
// ...minor dirty hack
final PointD top = transformer.getValuesByTouchPoint(0, 0);
final PointD bottom = transformer.getValuesByTouchPoint(0, mChart.getHeight());
final int diff = (int)(top.y - bottom.y);
// draw 2-9 axis labels
final int count = Math.min(9, Math.max(diff, 2));
Log.d("scale", String.format("scale %f: diff %d and count %d", scaleY, diff, count));
// "force" the count, for there are drawing issues where none get drawn on high zoom levels (just try it out)
yAxis.setLabelCount(count, true);
}
// todo implement other interface methods
The value formatter and everything else stays the same.
And some ugly screenshot to show that it works :D
code like this:
mchart.setAutoScaleMinMaxEnabled(false);
mchart.getAxisLeft().setAxisMaxValue(10);
mchart.getAxisLeft().setAxisMinValue(5);
mchart.getAxisRight().setAxisMaxValue(10);
mchart.getAxisRight().setAxisMinValue(5);
or:
boolean a = isReady;
mchart.getAxisLeft().setFormater(new format(float b){ return "" ;})
When u get data :
mchart.setAutoScaleMinMaxEnabled(true);
mchart.getAxisLeft().resetAxisMaxValue();
mchart.getAxisLeft().resetAxisMinValue();
mchart.getAxisRight().resetAxisMaxValue();
mchart.getAxisRight().resetAxisMinValue(5);
I have no code by my hand.
You can set granularity to your required value to prevent the repetition when zoomed.
mBarChart.getAxisLeft().setGranularity(1f); // y-axis scale will be 0,1,2,3,4....
mBarChart.getAxisLeft().setGranularityEnabled(true);
If you want to set granularity dynamically, then implement IAxisValueFormatter and compare the return value to get the difference and set Granularity to that difference.
private float yAxisScaleDifference = -1;
private boolean granularitySet = false;
//say the values returned by IAxisFormatter is in hundreds: 100, 200, 300...
mBarChart.getAxisLeft.setValueFormatter(new IAxisValueFormatter() {
#Override
public String getFormattedValue(float v, AxisBase axisBase) {
if(!granularitySet) {
if(yAxisScaleDifference == -1) {
yAxisScaleDifference = v; //10
}
else {
float diff = v - yAxisScaleDifference; //200 - 100 = 100
if(diff >= 1000) {
yAxisLeft.setGranularity(1000f);
}
else if(diff >= 100) {
yAxisLeft.setGranularity(100f); //set to 100
}
else if(diff >= 1f) {
yAxisLeft.setGranularity(1f);
}
granularitySet =true;
}
}
return val;
}
});
Another Example:
say Y-Axis returns [1200,3400,8000,9000....]
first time: 1200
second time: 3400 - 1200 = 2200
granularity set to 1000
If the difference is not uniform you have to use array to store the differences and take the average to get the right granularity.
If you are using IAxisValueFormatter the problem might be in the conversion of float to Int when trying to access the values array.
For me the solution was to
IAxisValueFormatter numAppointmentsXAxisFormatter = new IAxisValueFormatter() {
#Override
public String getFormattedValue(float value, AxisBase axis) {
int index = (int)Math.ceil(value);
if(index < 0){
index = 0;
}else if(index >= numAppointmentsLabels.size()){
index = numAppointmentsLabels.size()-1;
}
return numAppointmentsLabels.get(index);
}
};
I also added +1 to the label count
chart.getXAxis().setLabelCount(numValue+1, true);
Hope it helps
I have never used MPAndroidCharts before, but just a little search here and there got me this method which I think would be useful.
public void setLabelCount(int count, boolean force) {
if (count > 25)
count = 25;
if (count < 2)
count = 2;
mLabelCount = count;
mForceLabels = force;
}
The description says that "exact specified count of labels will be drawn and evenly distributed alongside the axis". If you can make it work in your favor, you might be able to limit the zoom.
Also, there is another method-
public int getLabelCount() {
return mLabelCount;
}
This returns the number of labels on the axis. Hope this helps.
https://github.com/PhilJay/MPAndroidChart/blob/5a15715b25991e3d61d27d552f9eba45975d65e7/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java