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);
Related
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)
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);
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
As question title, I want to use the change values of accelerator at three axis x,y,z to test that device is standing still or is moving.
I can use titanium to get values of accelerator in 3 axis:
Ti.Accelerometer.addEventListenter('update',function(e))
{
var x=e.x;
var y=e.y;
var z=e.z;
var timestamp=e.timestamp;
}
In real device, those values change continuously. I want to calculate the change between two times update consecutive. But I need some pointers on how to do the calculation.
How about in addEventListener you keep 3 static variables or a single static structure containing the last values and calculate the abs() difference on them and the current values?
Pseudo code ( handling just one variable - expand to three ):
int f( int x )
{
static int old_x = -1;
if( x != old_x )
{
// movement detected and do something
old_x = x;
}
else
{
// no movement
}
}
}
you can use Ti.App.Properties variables to store values if you want. Instead of your pseudocode's c++ style static variable, use a property and update it at the end of your event listener.
http://developer.appcelerator.com/apidoc/mobile/1.8.2/Titanium.App.Properties-module