I'm using achartengine in my Android Application, it works well but i have a question.
Is it possible to reverse plot?
I mean in my graph, new values which are added to my XY series with the function add, are added at end of the series, and then the graph is redrawn, so new values appears at right of the graph.
But i want to add my new value at index 0, in order to show on the graph only the last X values.
Sorry if it's not very clear
Thanks
There is no support for inserting data to XYSeries at a given index. However you could get to this behavior by clearing the current data and adding it back, with the new value included. I know this would not be a very optimal way, but it helps you get to your needed behavior.
Edit: I added an add(index, x, y) method in XYSeries. You can download a version including this feature here.
So, i've found a trick:
Dataset is my XYseries and mRenderer my multipleSeriesRenderer
I've changed alignment of the Y axis:
mRenderer.setYAxisAlign(Align.RIGHT, 0);
I've erased automatic labels:
mRenderer.setXLabels(0);
The 0 on the axe X is now a custom label, so every time a new value is added to the graph, I have to change is position:
mRenderer.setXAxisMax(dataset.getItemCount() - 1); mRenderer.addXTextLabel(dataset.getItemCount() - 1, "0");
And to finish, i change the X axis min everytime a new value is added, in order to get a fix scale:
mRenderer.setXAxisMin(dataset.getItemCount() - scale - 1);
Related
The Problem I am having is that I have charts which should always show a fixed range of XValues let's say all 24 hours in a day, but the Chart is only showing XValues up to and starting from the point of the first and last YValue, that is if I have two Y events, let's say 2am and 3pm, instead of showing the whole 24 hours, it will start at 2am and end at 3pm.
I think this has something to do with the new way to handle XValues via IAxisValueFormatter, since this used to work fine when we could add both X and Y values to a ChartData.
One hack to workaround this I found is to add empty YValues to first and last hour in my case 0 values, but this brings another issue that no matter what I set the minimum in LeftAxis it starts showing negative label values (starts in -15 instead of 0).
Is there an official way to do this? I have researched quite a bit about this and I am thinking on going back to a previous version of the library where I could just use the old way.
Edit: Just to clarify the problem doesn't have anything to do with the labels, but with the start and end of the Chart in X, it is discarding the range of X which doesn't have any YValues which I understand makes sense but it makes the results look ugly in certain cases.
You can use the setLabelCount() method to force the axis to draw labels according to the count you specify
According to the documentation:
setLabelCount(int count, boolean force)
#param count: the number of y-axis labels that should be displayed
#param force if enabled, the set label count will be forced, meaning that the exact specified count of labels will be drawn and evenly distributed alongside the axis - this might cause labels to have uneven values
And the setLabelCount method is defined below
public void setLabelCount(int count) {
if (count > 25)
count = 25;
if (count < 2)
count = 2;
mLabelCount = count;
mForceLabels = false;
}
You can use setLabelCount() with setAxisMaximum() and setAxisMinimum()
For example:
axis.setLabelCount(24, true);
axis.setAxisMaximum(24f);
axis.setAxisMinimum(0f);
This will draw values from 0 - 24 regardless of Y-Axis values
I have intention on looking for a specific point in a line chart of MPAndroidChart and then display the the marker to highlight the point after a button is hit. The example given is where the marker is only displayed after touching event which is different in my case. I tried code below but to no avail, can some one please teach me I would appreciate.
Highlight h = new Highlight((int) valIndex, linechart2.getData().getDataSetCount());
linechart2.highlightValue(h, true);
mv2.refreshContent2(valueYAxis.get((int) valIndex), h);
linechart2.getMarkerView();
linechart2.setDrawMarkerViews(true);
linechart2.getData().setHighlightEnabled(true);
// RefreshChart();
linechart2.invalidate();
You can easily highlight values programmatically by using one of the following methods on your Chart object:
highlightValues(Highlight[] highs): Highlights the values at the given indices in the given DataSets. Provide null or an empty array to undo all highlighting.
highlightValue(int xIndex, int dataSetIndex): Highlights the value at the given x-index in the given DataSet. Provide -1 as the x-index or dataSetIndex to undo all highlighting.
It's all in the wiki.
the makerview will show when the point is highlighted, so you can try this
Highlight h = new Highlight((int) valIndex, 0);
mv2.refreshContent2(valueYAxis.get((int) valIndex), h);
linechart2.setMarker(mv2);
linechart2.highlightValue(h);
I use the Amazing MPChart, however i have trouble setting other than index values
on on the X-Axis.
Do anyone know how to set it, should i modify labels of the axis?
The documentation say that the x-value is set in the data object, bit
X-values is always and index, as far as i can see.
My goal is to have values of time on the x-axis, statistics for 1 week 2 weeks one month etc.
You can do this by using these line of code. You can understand this code if you are familiar with mpchartlibrary android.
ArrayList<String> xVals = new ArrayList<String>();
xVals.add("1 week");
xVals.add("1 Month");
data= new LineData(xVals, setData);
mChart.setData(data);
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);
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.
For those who googled for chart squeezing problems inside ScrollView with AChartEngine this is solution to your problem:
renderer.setInScroll(true);