I use actually the AndroidPlot library to use a simple chart in my android project but I don't know how i can change the values of domain zone.
More specific, this line:
mySimpleXYPlot.setDomainValueFormat(new DecimalFormat("#"));
In the web site said that i can use another formats and its true, but if I use for example:
SimpleDateFormat("dd-MM-yyyy")
In the chart appears "31-12-1969" in all domain values.
Somebody know how I can change that date? or use another format (like String)?
Late answer, but maybe will be useful to other people.
I also had a hard time with this issue, especially since I am Java beginner.
I implemented a custom formatter. Seems a bit ugly solution but it works. Idea is the following:
take only Y axis for values, and leave X axis as indexes into an array (as Androidplot tutorial suggests, use using ArrayFormat.Y_VALS_ONLY, // Y_VALS_ONLY means use the element index as the x value)
each time your data changes, you need to pass to the Plot a new formatter with your new data for X axis
Here are some code snippets.
First is the class which transforms array index to a custom label String:
public class MyIndexFormat extends Format {
public String[] Labels = null;
#Override
public StringBuffer format(Object obj,
StringBuffer toAppendTo,
FieldPosition pos) {
// try turning value to index because it comes from indexes
// but if is too far from index, ignore it - it is a tick between indexes
float fl = ((Number)obj).floatValue();
int index = Math.round(fl);
if(Labels == null || Labels.length <= index ||
Math.abs(fl - index) > 0.1)
return new StringBuffer("");
return new StringBuffer(Labels[index]);
}
And here is how I attach it to the Plot:
MyIndexFormat mif = new MyIndexFormat ();
mif.Labels = // TODO: fill the array with your custom labels
// attach index->string formatter to the plot instance
pricesPlot.getGraphWidget().setDomainValueFormat(mif);
This trick works also for dynamic updates.
NOTICE: Androidplot seems to have problems with drawing horizontal lines, so if your data has the same Y values, you might get strange results, I already asked for help on this issue.
Related
I am appending a row to a google sheet using the api and it works fine but the last object in the row is a formula. instead of changing to reflect the row it is on like =E3-D3, =E4-D4, it stays static and always puts =E3-D3 in the row. The formula works for that row only.
This is for android and I am using the Java library. I know there must be an easy way to do this, its so common but I am missing it.
here is a code sample:
these are the objects I am passing in: o6 is the formula and it is wrong, but I am not sure how to fix.
Object o1 = result.getDate(), o2 = result.getDescription(), o3 =
String.valueOf(result.getDistance()), o4 = result.getStartTime(),o5 =
result.getEndTime(), **o6 ="=E3-D3";**
//for the values that you want to input, create a list of object lists
List<List<Object>> values = new ArrayList<>();
//values.add(data1);
//todo me
values.add(data);
//Create the valuerange object and set its fields
ValueRange valueRange = new ValueRange();
valueRange.setMajorDimension("ROWS");
valueRange.setRange(range);
valueRange.setValues(values);
AppendValuesResponse avResponse = null;
try {
avResponse = this.mService.spreadsheets().values()
.append(mSpreadSheetId, range, valueRange)
.setValueInputOption("USER_ENTERED")
.execute();
Up until now all the formulas I have used occupied a single cell and summed a whole column.
Use relative formulae instead of absolute formulae with R1C1 notation.
There are two positioning notations used in Google Sheets. The first, called A1 notation, uses characters from the Latin alphabet to indicate the column, and integers to indicate the row of a cell. The second, called R1C1 notation, uses integers to represent both the column and the row, and precedes each by a corresponding R or C, to indicate row or column number. The addresses A1 and R1C1 are equivalent, as are the addresses B5 and R5C2.
So for example, if the cell you want to update is in column H, but you want it to always reflect the row even if the column is different, use relative notation to do this. The INDIRECT formula keyword can help you here:
=E3-D3
becomes:
=INDIRECT("R[0]C[-3]", FALSE)-INDIRECT("R[0]C[-4]",FALSE)
For column H.
I have a temperature value from the Bluetooth device.
StringBuilder [] temp = new StringBuilder[1000];
it is not empty, it includes temperature value, for example, temp[1]=20, temp[2]=30 like this. But every one second this array change with news so my string is dynamic. I want to draw graph time-temp (x: time, y: temp) if I saw firstly temp[1] and draw ( a mean real-time graph). But the mean problem is, how can I draw the graph with the values (using Graphview library), I have StringBuilder and how to read them for the graph. ? Please help me I don't find any answer
I'm using MPAndroidChart and I know this topic is covered quite a bit in the docs, so apologies if I've missed something obvious, but I'm having a bit of trouble formatting timestamp values into dates on the x-axis of my Linechart.
It appears that getFormattedValue() isn't being invoked for my x-axis value for whatever reason. If i debug AxisBase, it only seems to looking to format the y-axis values, which i do not have a custom formatter set on.
Here is the code snippets, taken mostly from the Github docs:
LineChart chart = (LineChart) findViewById(R.id.chart);
XAxis xAxis = chart.getXAxis();
// set min timestamp to Jul 2017
HourAxisValueFormatter(Long.parseLong("1499814559"));
xAxis.setValueFormatter(new IAxisValueFormatter() {
// THIS IS NEVER INVOKED!
#Override
public String getFormattedValue(float value, AxisBase axis)
{
return new Date(Long.parseLong(""+value)).toString();
}
});
// rating is a map of timestamp to numeric value, both stored
// as strings
for (Map.Entry<String, String> rating : ratings.entrySet()) {
String timestamp = rating.getKey();
String ratingValue = rating.getValue();
entries.add(new Entry(Float.parseFloat(timestamp),
Float.parseFloat(ratingValue)));
}
// add entries to dataset
LineDataSet dataSet = new LineDataSet(entries, "Ratings");
LineData lineData = new LineData(dataSet);
chart.setData(lineData);
chart.invalidate(); // refresh'
I'm using version 3.0.2 of the library:
compile 'com.github.PhilJay:MPAndroidChart:v3.0.2'
Thanks in advance, Gary
EDIT per request for desired output/actual output:
Ideally i would have a series of dates along the x-axis , e.g. 10/7, 11/8, 12/8, etc. constructed from the Epoch values I've provided. I know the code above wont format it in that format as it stands, but just want to get it formatting to any date value initially (so ignore that for now), the crux of the issue is that my formatter isn't getting invoked at all.
Below is a screenshot of the current output, it only prints a single value on the x=0 line (note even though there are multiple y values being provided, i wonder if they are all on the same x=0 line does it just draw the last point or something?):
Debugging the timestamp values above, Float.parseFloat(timestamp) is equal to 1.50516885e^12. The actual timestamp value for example is 1505168846751, but after parsing to a Float is rounded, and given an exponent value.
EDIT 2 :
Screen grab of the values supplied as 'entries' to the LineDataSet:
EDIT 3:
The issue appears to be to do with the size/format of the timestamp values for the x-values I'm providing, changing these to small float values in the range 1.0 -> 20.0f, causes the formatter to be invoked as expected. I need to debug the code further to see why the exponential timestamp values are not being formatted.
From looking into this i think this is a limitation at the moment, for this specific use case (timestamps are very close together) since Entry will only accept floating point values, my timestamps are all getting passed as 1.50516885e^12, even though the precise timestamp values are slightly different. When AxisRenderer works out the range for the x-axis then is sees it as 0, and sets the entries to 0 also, in this block here
This question has been made here, but still has got no answer...
Using StackedBarActivity example from MPAndroidChart library to draw a 3 merge bars, and setting the values as [1,2,3]... the chart is showed with a total of all numbers, 1+2+3=6.. but what I want is to merge all values in order to value 2 overlay value 3 and value 1 overlay value 2, as showed on the image bellow:
Basically, I want to use the StackedBarActivity activity, but not stack all the bars, instead, I want to put one behind another.
Visually I know I can subtract the bigger value with the smaller, making a sum until reaching 3 (1+1+1), but then the value 3 will retain value 1 and not value 3.
Is there a way I can do this using this class? Is there a better class to do this?
I know I am like 6 months late with answer, but I think that is working solution:
List<String> xVals = getXVals(); //some function to get values
List<BarEntry> yVals = new ArrayList();
int[] barColors = new int[bars.size() * numberOfValues];
int index=0;
for (Bar bar : bars) {
List<BarEntry> yValsForBar = new ArrayList();
for (int i=0; i<numberOfValues; i++) {
yValsForBar.add(new BarEntry(bar.value(i), i));
barColors[i+index*numberOfValues] = bar.color();
}
yVals.addAll(yValsForBar);
index++;
}
BarDataSet dataSet = new BarDataSet(yVals, "data set");
BarData data = new BarData(xVals);
data.addDataSet(dataSet);
And here, you should have overlying bars in different colors (note: of course you might not see some bars if they have bigger values than next ones, if you wan't to sort them you will have to do some modifications to this). At least works with me.
Expanding on n4yArh's answer.
With the latest version of the library, the constructor for BarEntry has changed to BarEntry(x,y).
So the line
yValsForBar.add(new BarEntry(bar.value(i),i));
should be changed to
yValsForBar.add(new BarEntry(i,bar.value(i));
and of course to use the color array, the following line is missing
dataSet.setColors(barColors);
I'ms setting custom text labels on my line chart, using this on the renderer:
String[] xLabelsForTimeScale = getXLabelsForCurrentTimeScale(); //weekday names
for (int i = 0; i < xLabelsForTimeScale.length; i++)
{
mRenderer.addXTextLabel(i, xLabelsForTimeScale[i]);
}
mRenderer.setXLabels(0);
mRenderer.setShowCustomTextGridX(true);
when the chart renders, it's only displaying x labels for points where I have a non null series value. For example, assume that the xLabelsForTimeScale array is an array of weekday abbreviations. If I have only two values, say for Mon, Tue, it only shows labels for Mon and Tue. I'd like to display all the x axis labels, whether there's a series point or not. Sun - Sat, basically. How can I do that?
ADDITIONAL INFO ON REQUIREMENT: I don't want to add zero, dummy points within the series if I can at all help it. What I expect to happen is the line just renders between actual points, connecting each actual, valid point, in a linear fashion. If I add zero, dummy points, there will be a lot of pointy tops (lack of a better term) as the line draws between valid point data, and placeholder, dummy data. Hope that makes sense. Thanks.
You can avoid this for time charts by calling:
renderer.setXRoundedLabels(false);