I want to integrate a simple XY line chart in my Activity. While looking for free charting with customization (customizable backgrounds, colors, axis labels), I found two candidates: Achartengine and Adnroidplot. There were some other libraries, but they were not customizable or available only as separate Intents.
I need also support for older Android API (at least 1.6 must be supported).
I tried Achartengine but it failed when I integrated it in a ScrollView. When I was scrolling, the chart became somehow corrupted, it got squeezed and some background elements seemed to drift away.
Then I tried Adnroidplot. At first it did not start on 1.6 because of a Pair class. But I found a fix for the problem on Adnroidplot forum. Everything seemed to work fine, also dynamic updates though custom Observers worked fine. It was a bit hard to customize X axis labels (I needed custom Strings there and not numbers), but with a custom formatter I finally did it.
But then I tried it with real data from a client's database. There were some series of points with equal values. And I was shocked to see that Adnroidplot is not able to draw a horizontal line, it hangs or completely messes up the chart!
Here is the test case, I borrowed it from Adnroidplot Quickstart and did a small modification to make one series with equal values:
pricesPlot = (XYPlot) findViewById(R.id.mySimpleXYPlot);
// Create array of y-values to plot:
Number[] series1Numbers = {7, 7}; // horizontal line expected, got nothing or hang
// Turn the above arrays into XYSeries:
XYSeries series1 = new SimpleXYSeries(
Arrays.asList(series1Numbers), // SimpleXYSeries takes a List so turn our array into a List
ArrayFormat.Y_VALS_ONLY, // Y_VALS_ONLY means use the element index as the x value
"Series1"); // Set the display title of the series
// Create a formatter to use for drawing a series using LineAndPointRenderer:
LineAndPointFormatter series1Format = new LineAndPointFormatter(
Color.rgb(0, 200, 0), // line color
Color.rgb(0, 100, 0), // point color
null); // fill color (optional) <- my app hangs if I add it for a horizontal line
// Add series1 to the xyplot:
pricesPlot.addSeries(series1, series1Format);
// Reduce the number of range labels
pricesPlot.setTicksPerRangeLabel(3);
// By default, AndroidPlot displays developer guides to aid in laying out your plot.
// To get rid of them call disableAllMarkup():
pricesPlot.disableAllMarkup();
I already posted on Adnroidplot forums, but I am not sure how fast they will answer and when the issue will be fixed.
So I hope maybe someone at StackOverflow might know some workaround for it?
Thanks to the developers on Androidplot forums, I now got the solution. The following code is a fragment of my Activity.java file. Unfortunately the final code was later refactored and some pieces moved to a custom datasource and custom XYSeries which I don't have permissions to publish here.
This code worked for Androidplot-core-0.4.4-release.jar, and I'm not sure if it will work with later versions.
// for chart
private XYPlot pricesPlot;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ... other initialisation code omitted for brevity ...
pricesPlot = (XYPlot) findViewById(R.id.mySimpleXYPlot);
// the following code was added as a debug code to test that it works.
// later many things were changed, so take it "as is" - this was the core of the solution
PriceDatesFormat ppf = new PriceDatesFormat();
ppf.Labels = new String[]{
"2011-01",
"2011-05",
"2011-07",
"2011-11",
"2011-07",
"2011-07"
};
pricesPlot.getGraphWidget().setDomainValueFormat(ppf);
// Create two arrays of y-values to plot:
Float [] seriesNumbers = new Float[]{118f, 185f};
Float min = Collections.min(Arrays.asList(seriesNumbers));
Float max = Collections.max(Arrays.asList(seriesNumbers));
pricesPlot.setRangeBoundaries(min - 0.1*min, max + 0.1*max, BoundaryMode.AUTO);// make them a bit wider out of min/max values
I came up with an easy workaround to make sure horizontal lines are shown.
Basically, just graph a 3 point clear Y_VALS_ONLY series before you load your first real plot.
Assuming you have a colors.xml res file, you can create a clear series like this:
Declare this:
Number[] yClear = {0, 1, 0};
LineAndPointFormatter clearFormat;
SimpleXYSeries clear= null;
In your onCreate() or onViewCreated():
clearFormat = new LineAndPointFormatter(getResources().getColor(R.color.transparent), getResources().getColor(R.color.transparent), 0, null);
Then after you set up your plot, just add the clear plot to the graph;
clear = new SimpleXYSeries( Arrays.asList(yClear), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Clear");
yourPlot.addSeries(clear, clearFormat);
I spent hours trying to debug this issue, and it came down to just making life easy and doing it this way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With