I am using android-graphview to display bar graph in android app. On X-axis I want to display labels as 'day-of-the-week,hour-of-the-day' like 'Mon,14.00'. So original x value(it may be date or time in milliseconds) in data point is totally done away with. I know we can do some customization in setLabelFormatter, but as far as I understand you can do some append to original value, not totally remove it.
Is there a way out for it?
use the DefaultLabelFormatter override the format method and call the super implementation. then you can append your text to the string.
Example:
graph.getGridLabelRenderer().setLabelFormatter(new DefaultLabelFormatter() {
#Override
public String formatLabel(double value, boolean isValueX) {
if (isValueX) {
// show normal x values
return super.formatLabel(value, isValueX);
} else {
// show currency for y values
return super.formatLabel(value, isValueX) + " €";
}
}
});
Related
I need to draw graph like the image i have uploaded , i am using MP chart library and develop a graph but want to customize it according to my requirement but not able to find solution for my requirements my basic requirement is for x axis i want to show custom values at axis like 5-11 12-18 but i am passing value to x axis like this
private ArrayList<String> setXAxisValues() {
ArrayList<String> xVals = new ArrayList<String>();
xVals.add("10");
xVals.add("20");
xVals.add("30");
xVals.add("30.5");
xVals.add("40");
return xVals;
}
So it is showing x values like this 10 20 30 so on so i want my graph to be built upon using these x value which is happening right now but want to show custom value at bottom like 5-11 etc and this value is dynamic coming from Api response so please help me about this , Waiting for positive and early response Thanks in Advance
To format the x-axis values, you should use the setValueFormatter method which takes a callback interface were you have to implement the getFormattedValue method which is called before drawing the x-axis value.
xAxis.setValueFormatter((value, axis) -> {
String res = "";
try {
// get current position of x-axis
int currentPosition = (int) value;
// check if position between array bounds
if (currentPosition > -1 && currentPosition < maxSize) {
// get value from formatted values array
res = xVals.get(currentPosition);
}
} catch (Exception e) {
// handle exception
}
return res;
});
How to set J SON data in bar entry in two decimal point?
You can use The ValueFormatter interface
The IValueFormatter interface can be used to create custom-made formatter classes that allow to format values within the chart (from DataSets) in a specific way before drawing them.
For using the IValueFormatter, simply create a new class and let it implement the interface and return whatever you want to be displayed from the getFormattedValue(...) method.
Creating a Formatter
public class MyValueFormatter implements IValueFormatter {
private DecimalFormat mFormat;
public MyValueFormatter() {
mFormat = new DecimalFormat("###,###,##0.0"); // use one decimal
}
#Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
// write your logic here
return mFormat.format(value) + " $"; // e.g. append a dollar-sign
}
}
Then, set your formatter to the ChartData or DataSet object:
// usage on whole data object
lineData.setValueFormatter(new MyValueFormatter());
// usage on individual dataset object
lineDataSet.setValueFormatter(new MyValueFormatter());
Predefined Formatters
LargeValueFormatter: Can be used for formatting large values >
"1.000". It will turn values like "1.000" into "1k", "1.000.000" will
be "1m" (million), "1.000.000.000" will be "1b" (billion) and values
like one trillion will be e.g. "1t".
PercentFormatter: Used for
displaying a "%" sign after each value with 1 decimal digit.
Especially useful for the PieChart. 50 -> 50.0 %
StackedValueFormatter: A formatter specifically designed to be used
with stacked BarChart. It allows to specify whether all stack values
should be drawn or just the top value.
I have tried figuring this out, but it doesn't add up. The data doesn't appear as it should.
First I generate dummy data. This is done async because I need time between the calls to System.currentTimeMillis to get some spacing between them. (Look aside the crappy code here, this is just debug data that will not be in the release. Using Thread.sleep on the main thread is a bad idea considering ANR's)
public class AsyncGeneration extends AsyncTask<String, String, String>{
public AsyncGeneration() {
super();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
#Override
protected void onCancelled(String s) {
super.onCancelled(s);
}
#Override
protected void onCancelled() {
super.onCancelled();
}
#Override
protected String doInBackground(String... strings) {
while(root == null) {
try {
Thread.sleep(200);
}catch(InterruptedException e){}
}
List<Entry> rdata = new ArrayList<>();
for(int i = 1; i < 30; i++){
try{
Thread.sleep(200);
}catch(Exception e){
//IGNORE
}
float time = System.currentTimeMillis();
Log.e("GChart", "Timex: " + time);
Session s = new Session(r.nextInt(5000), time);//Replace time with the index in the for-loop and it works for some reason
rdata.add(new Entry(s.getXValue(), s.getYValue()));
Log.e("GChart", "Timey: " + s.getXValue());
}
final List<Entry> entries = rdata;
OverviewFragment.this.getActivity().runOnUiThread(() ->{
LineDataSet data = new LineDataSet(entries, "Distance");
data.setCircleColor(Color.parseColor("#FF0000"));
LineData lineData = new LineData(data);
tab1chart.setData(lineData);
tab1chart.invalidate(); // refresh
tab1chart.getXAxis().setValueFormatter(new DateFormatter());
tab1chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);
tab1chart.getXAxis().setTextSize(10f);
tab1chart.getXAxis().setTextColor(Color.RED);
tab1chart.getXAxis().setDrawAxisLine(true);
tab1chart.getXAxis().setDrawGridLines(true);
tab1chart.getAxisLeft().setValueFormatter(new DistanceValueFormatter());
tab1chart.getAxisLeft().setDrawGridLines(true);
Log.v("Chart", "Chart data loaded and invalidated");//This prints
});
return null;
}
}
So far everything looks fine. The data gets put into the chart, no exceptions, no crashes.
When the chart renders, a single data point shows up at the far-left of the chart. I generate 30 data points, one shows up.
That's issue #1: Only one data point shows up.
Issue #2 is slightly harder. The entire X axis at the bottom disappears. X axis is gone and when zooming, the Y axis, and its text also disappears. This is fairly hard to explain, so here is a screenshot:
It is worth mentioning the fact that if I pass i in the for-loop as the time, it shows up just as expected: all the axises are in place, zoom doesn't break anything.
(Float values can take the same values as Longs except they have decimals in addition.)
And in addition, I format the data:
public class DateFormatter implements IAxisValueFormatter {
SimpleDateFormat formatter;
public DateFormatter(){
formatter = new SimpleDateFormat("dd/MM/yy, HH:mm");
}
#Override
public String getFormattedValue(float value, AxisBase axis) {
//This method is never called. Nothing is returned
if(axis instanceof XAxis) {
String formatted = formatter.format(new Date((long) value));
Log.d("Formatter", "Formatted \"" + value + "\" to \"" + formatted + "\".");
return formatted;
}
return "Not supported";
}
}
Removing the formatter doesn't change anything, the axis is still gone. Zoom still breaks the Y axis.
So my question is: How do I fix this? I don't get why the chart doesn't work when I pass the current time in milliseconds (and I checked the values with debug output, floats can handle it). I got some debug output earlier that eventually stopped coming at all that showed the value passed to the formatter was values < 2000. I can't reproduce this any more though
The chart itself doesn't appear to be broken but from touch events it looks like every single point is pushed into the same X coordinate but only one point renders. When I touch the chart, the orange-ish lines show up indicating the position of a data point. It pops up on points that aren't visible.
When I pass the for-loop index as the X value, it works as expected, the formatter works fine (looking aside the fact that it shows the date as in 1970, but it is counted as 1 millisecond into the epoch, so that is to expect)
I looked at this as well on formatting the date. When I then try passing the milliseconds since the epoch, the chart stops working.
I'm using MPChart v 3.0.2, compiling against Android 26, using Java 8, and running Android Studio 3.0 beta 2
As for the layout, it is just a LinearLayout with a LineChart in it.
This should work, but it breaks when I pass it the current time in milliseconds for some reason. Passing any other data (as long as the numbers aren't that big) works fine.
The two images are not how the chart is supposed to look. The X axis is supposed to be visible, but for some reason it isn't along with a large amount of the data.
This is known issue of Android MPChart (have a read this thread). Time series chart supported in MPChart - You can set time (in millis) as X values for Hourly Charts.
But too many consecutive data (points) won't correctly plot in Line Charts. Because Entry object will accept only float values due to some performance constraints.
So, keep the first value as the reference and subtract each up coming value from reference value & divide by some constants (say 1000) .So , you X value set will be like 10,20,30....& so on.
Do the reverse logic in your Axis Value formatter to render the X Axis Label properly (see the code snippet).
lineChart.getXAxis().setValueFormatter(new IAxisValueFormatter() {
#Override
public String getFormattedValue(float value, AxisBase axis) {
SimpleDateFormat format2 = new SimpleDateFormat("HH:mm:ss");
return format2.format(new Date(firstTimeStamp + ((long) value) * 1000L));
}
});
Hello I have a really simple qestion, in my app I have an EditText and what I would like for instance is this:
If I write 1/2 I would like 0.5 in the field.
How can I do this?
only add any dight/any other digit or any text with this fraction?
need info
Why you "dont want to split the string and then covert to individual strings to numbers and then divide them to have result"?
I am not aware of any built-in function to do that so the simplest solution:
double parse(String ratio) {
if (ratio.contains("/")) {
String[] rat = ratio.split("/");
return Double.parseDouble(rat[0]) / Double.parseDouble(rat[1]);
} else {
return Double.parseDouble(ratio);
}
}
It also covers the case where you have integer representation of ratio
parse("1/2") => 0.5
parse("3/7") => 0.42857142857142855
parse("1") => 1.0
In my Android application I have to show my income and expense amounts in a piechart. The expense amounts will be negative. The amounts are of type float. So is it possible to display both negative and positive values in a pie chart using MPAndroidChart library?
I have tried with some negative and positive integer values and the result is horible. The pie-chart will behave crazy like a rummy board or illumination screen.
If I can't have negative values in a pie chart, is it possible to show the labels in negative by even though the actual values are positive?
You are essentially asking how to customise the labels on an MPAndroidChart chart. This can be done easily by writing your own implementation of the interface IValueFormatter.
IValueFormatter has one method that you need to implement:
getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler)`
You use the parameters of the method to construct the label you want as a String. You want a minus sign "-" in front so you simply do this:
return "-" + mFormat.format(value) + " %";
Here is the complete implementation:
public class NegativePercentFormatter implements IValueFormatter
protected DecimalFormat mFormat;
public NegativePercentFormatter() {
mFormat = new DecimalFormat("###,###,##0.0");
}
public NegativePercentFormatter(DecimalFormat format) {
this.mFormat = format;
}
#Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
return "-" + mFormat.format(value) + " %";
}
}