Android - MPAndroidChart - Overlay 3 bars - android

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);

Related

MPAndroidChart specify values on X-axis and scaling axises to the screen

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);

How can i write these items for constructor in a for-loop?

so I'm currently writing an app for android, and im still a noob in java/android.
Anyways i have this 2 strings, one with names and the other with emails, and i want to output them in a listview with a custom adapter.
It works fine so far but i dont know how to set the items dynamically (with a for loop).
To create the adapter and so on, I used this tutorial:
http://www.ezzylearning.com/tutorial/customizing-android-listview-items-with-custom-arrayadapter
I simply changed the ImageView to a second TextView.
In the tutorials code there are 5 items added to the list, but i need them dynamically, since Im not always having the same amount of name+emails to output
I already tried putting it in a for-loop by doing:
Weather weather_data[] = new Weather[names.length];
for(int z=0; z == names.length){
Weather[z]={new Weather(names[z], emails[z])};
}
I also tried it with adding "new" infront and trying to set everything null before, basically trial&error since i dont know much about it.
So can anyone tell me how I add the items dynamically?
(Ps: sorry if I used wrong names to describe anything)
This should work
Weather weather_data[] = new Weather[names.length];
for(int z=0; z < names.length; z++){
weather_data[z] = new Weather(names[z], emails[z]);
}
Give this a read to learn how for loops work
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html
and this one for arrays
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
try this
ArrayList<Weather> weatherData = new ArrayList<>();
for (int i=0; i < names.length(); i++){
weatherData.add(new Weather(names[i], emails[i]));
}
Then when you need it as a Weather[] use weatherData.toArray()

Android Stacked Bars Chart

I'm using the MPAndroidChart library, trying to customize the Stacked Bars.
The objective is to display the differences between 2 currencies.
So suppose this example for January.
Currency #1 = 8;
Currency #2 = 12
The idea is to show in the same bar both values, but instead of sum the 2 values ( 8 + 12) to have the value 8 "in front" and the value 12 "behind".
So the total high of the bar is the max value.
I tried to do that, extending the BarEntry class, and instead of calculate the sum, just set the max value. But I'm seeing only one bar now (the one with value = 12)
Do you know if this kind of logic is supported? Any advice?
Check out the guide on how to create stacked-bar-charts, as well as the example.
Create an entry in the stacked-bar-chart in the following way:
BarEntry entry = new BarEntry(xValue, new float[] { 8f, 12f });
This will create an entry with a total height of 20, consisting of two different values (8 and 12). The "xValue" is the position this bar will show up on the x-axis.
You can use as many entries for the stack (float array) as you want.
If you intend to do only single entries (no stacks), do not use the BarEntry constructor that takes a float array, use the one that only takes a single value.

Charting on Android - problems with androidplot and achartengine

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);

AndroidPlot: How i can change the domain data?

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.

Categories

Resources