Varying Bar Width on BarChart panning - Achartengine - android

I'm trying to make a BarChart using achartengine, but so far, I haven't been able to get rid of the following effect : bar width is only correctly displayed when values are on the edge of the screen, but at startup, bars are much bigger and sometimes even hide the bar's value. Could this have something to do with my data set not being a continued serie of x values ? I have one point at x=17 then then next value is at x=24, and it seems the changing bar width happens between these 2 values. Can someone assist in making this graph look good ?
Thanks in advance for your help !
[The graph being shown on fragment's start]
[The graph being shown when scrolling to the left]
CODE TO MAKE THE GRAPH :
XYSeries xySerie = new XYSeries("Climb Level Statistics");
XYSeriesRenderer serieRenderer;
XYMultipleSeriesDataset mDataset = new XYMultipleSeriesDataset();
XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer();
//Adding data to XYSerie and adding XYSerie to mDataset
//stats is an int[] containing level id, value for the level, level id, ...
//example of dataset used for image shown above: {17, 4, 24, 3, 25, 7, 26, 10, 27, 4}
int statsSize = stats.size();
double routeLevel;
double climbsQuantity;
for (int counter = 0; counter<statsSize; counter++){
routeLevel = stats.get(counter);
counter++;
climbsQuantity = stats.get(counter);
xySerie.add(routeLevel, climbsQuantity);
}
mDataset.addSeries(xySerie);
//Setting series renderer properties and adding it to the mRenderer
serieRenderer = new XYSeriesRenderer();
serieRenderer.setChartValuesTextSize(28);
serieRenderer.setDisplayChartValues(true);
mRenderer.addSeriesRenderer(serieRenderer);
//Setting main renderer properties
mRenderer.setApplyBackgroundColor(true);
mRenderer.setMarginsColor(Color.argb(0x00, 0x01, 0x01, 0x01));
mRenderer.setBackgroundColor(Color.TRANSPARENT);
mRenderer.setLabelsTextSize(15);
mRenderer.setMargins(new int[] { 30, 30, 30, 30 });
mRenderer.setZoomButtonsVisible(false);
mRenderer.setPanLimits(new double[]{0,48, 0, 5000});
mRenderer.setBarSpacing(1.5);
mRenderer.setLabelsTextSize(28);
mRenderer.setLabelsColor(Color.BLACK);
mRenderer.setXLabels(0);
mRenderer.setXLabelsColor(Color.BLACK);
String[] routeLevels = context.getResources().getStringArray(R.array.route_levels);
int routeLevelsSize = routeLevels.length;
for (int x=1;x<routeLevelsSize+1;x++){
mRenderer.addXTextLabel(x, routeLevels[x-1]);
}
mRenderer.setYLabels(0);
mRenderer.setYAxisMin(0);
mRenderer.setShowLegend(false);
mRenderer.setZoomEnabled(false);
mRenderer.setZoomEnabled(false, false);
mRenderer.setPanEnabled(true, false);
GraphicalView graphView = ChartFactory.getBarChartView(context, mDataset, mRenderer, BarChart.Type.STACKED);
graphView.setBackgroundColor(Color.argb(255, 247, 247, 247));

I was able to resolve the changing bar width issue by ensuring the serie was a "perfect" suite for x values, changing
this : {17, 4, 24, 3, 25, 7, 26, 10, 27, 4}
to this : {17, 4, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24, 3, 25, 7, 26, 10, 27, 4}
To achieve that, I modified my first for loop to check for missing x values :
for (int x = 0; x<statsSize; x++){
routeLevel = currentLevel;
x++;
currentLevel++;
climbsQuantity = stats.get(x);
xySerie.add(routeLevel, climbsQuantity);
//if not at the last x/y couple of the array, fill the blanks in the serie
if (x<statsSize-1){
while (stats.get(x+1)>currentLevel){
routeLevel = currentLevel;
climbsQuantity = 0;
xySerie.add(routeLevel, climbsQuantity);
currentLevel++;
}
}
}
Now the bar width doesn't change at all when I scroll. This is more a workaround, though, because now the "filling" couples I added are all showing 0 as value, which I find a bit odd. If I find a way to hide these 0 values, I'll edit my answer...
CURRENT APPEARANCE OF THE GRAPH

First of all, you can set the visible area by changing the X axis min and max:
renderer.setXAxisMin(min);
renderer.setXAxisMax(max);
For changing the bars width, you have a few options.
If your dataset contain more than one element per series then I suggest you use renderer.setBarSpacing().
If there is only one element in your series then you can use renderer.setBarWidth().

Related

How to change text colour for AndroidPlot domain and range labels?

Hi all I am just trying out a simple XY Plot with AndroidPlot. I am having trouble figuring out how to change the label colours for the domain and range. Examples online say to use:
plot.getGraphWidget().getDomainLabelPaint().setColor(my_colour);
plot.getDomainLabelWidget().getLabelPaint().setColor(my_colour);
However this does not compile for me. Can anyone suggest what I need to use? (I have also tried using getGraph() instead of getGraphWidget() )
I'm also trying to set margin space between the graph and domain labels, and also space between graph and range labels if anyone has a suggestion for that.
plot = (XYPlot) findViewById(R.id.plot);
plot.setPlotMargins(0, 0, 0, 0);
plot.getBackgroundPaint().setColor(Color.WHITE);
plot.setBorderStyle(XYPlot.BorderStyle.NONE, null, null);
plot.getGraph().getBackgroundPaint().setColor(Color.WHITE);
plot.getGraph().getGridBackgroundPaint().setColor(Color.WHITE);
plot.getGraph().getDomainOriginLinePaint().setColor(Color.TRANSPARENT);
plot.getGraph().getRangeOriginLinePaint().setColor(Color.TRANSPARENT);
// create a couple arrays of y-values to plot:
final Number[] domainLabels = {1, 10, 20, 6, 7, 8, 9, 10, 13, 14};
Number[] series1Numbers = {1, 4, 2, 8, 4, 16, 8, 32, 16, 64};
// turn the above arrays into XYSeries':
// (Y_VALS_ONLY means use the element index as the x value)
XYSeries series1 = new SimpleXYSeries(
Arrays.asList(series1Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series1");
// create formatters to use for drawing a series using LineAndPointRenderer
// and configure them from xml:
LineAndPointFormatter series1Format = new LineAndPointFormatter();
series1Format.setPointLabelFormatter(new PointLabelFormatter());
series1Format.configure(getApplicationContext(),
R.xml.line_point_formatter_with_labels);
LineAndPointFormatter series2Format = new LineAndPointFormatter();
series2Format.setPointLabelFormatter(new PointLabelFormatter());
series2Format.configure(getApplicationContext(),
R.xml.line_point_formatter_with_labels_2);
// add an "dash" effect to the series2 line:
series2Format.getLinePaint().setPathEffect(
new DashPathEffect(new float[]{
// always use DP when specifying pixel sizes, to keep things consistent across devices:
PixelUtils.dpToPix(20),
PixelUtils.dpToPix(15)}, 0));
plot.addSeries(series1, series1Format);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new Format() {
#Override
public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
int i = Math.round(((Number) obj).floatValue());
return toAppendTo.append(domainLabels[i]);
}
#Override
public Object parseObject(String source, ParsePosition pos) {
return null;
}
});
Looks like you found the answer to your text color problem.
As far as adjusting the spacing between your graph and the domain / range labels, as of Androidplot 1.x that's controlled by the graph's line label insets. For example, to adjust the relative positioning of range labels on the left edge of the graph:
programmatically:
// move line labels away from the graph by 5dp:
plot.getGraph().getLineLabelInsets().setLeft(PixelUtils.dpToPix(-5));
xml param:
ap:lineLabelInsetLeft="-5dp"

AchartEngine Barchart Spacing not working when orientation is vertical and number of elements are 2

I am having a AchartEngine Barchart. I have only two bars to show with Orientation as Vertical. The space between the two bars is very high and I am not able to change it. I have tried the following
1. Change the values passed to setBarSpacing() method from -100, -10, -.9, -.5, -.1, 0, .1, .5, .9, 10, 100
2. Used two XYSeries and then one. In both cases, the space is significant
3. Increased and decreased width of Bar
4. Set the min, max and values at different ranges. min = .9, max = 2.1, x1 = 1, x2 = 2
Nothing is working. Can some one please help me with this?
Try the following method.
The method below adds a barchart showing data for two months with values. If you want to change the color and some other properties, you are free to do that.
private void createChart() {
String[] mMonth = new String[] { "Jan", "Feb" };
int[] mData = new int[] { 20, 25 };
// creating XY series for Data
XYSeries series = new XYSeries("Performance");
// fill the data
for (int i = 0; i < mMonth.length; i++) {
series.add(i, mData[i]);
}
// create a dataset to hold each data series
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
// Adding dataseries to datast
dataset.addSeries(series);
// create a renderer to customize the series
XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setColor(Color.GREEN);
renderer.setFillPoints(true);
renderer.setLineWidth(2);
renderer.setDisplayChartValues(true);
renderer.setChartValuesTextSize(30);
// create a renderer to customize entire chart
XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer();
mRenderer.setXLabels(0);
mRenderer.setXTitle("Quarter 1");
mRenderer.setYTitle("Values in K");
mRenderer.setAxesColor(Color.BLACK);
mRenderer.setApplyBackgroundColor(true);
mRenderer.setBackgroundColor(Color.WHITE);
mRenderer.setMarginsColor(Color.WHITE);
mRenderer.setZoomButtonsVisible(false);
mRenderer.setZoomEnabled(false, false);
mRenderer.setPanEnabled(false, false);
// margins
int marginT = 50;
int marginL = 80;
int marginB = 15;
int marginR = 15;
mRenderer.setMargins(new int[] { marginT, marginL, marginB, marginR });
mRenderer.setShowLegend(false);
mRenderer.setAxisTitleTextSize(30);
// mRenderer.setChartTitleTextSize(20);
mRenderer.setLabelsTextSize(30);
mRenderer.setLegendTextSize(30);
// mRenderer.addXTextLabel(8, "OT");
mRenderer.setXAxisMin(-0.5);
mRenderer.setXAxisMax(3);
mRenderer.setYAxisMin(0);
mRenderer.setYLabelsAlign(Align.RIGHT);
mRenderer.setXLabelsColor(Color.BLACK);
mRenderer.setYLabelsColor(0, Color.BLACK);
mRenderer.setXLabels(0);
mRenderer.setBarSpacing(2);
// We want to avoid black border
// transparent margins
mRenderer.setMarginsColor(Color.argb(0x00, 0xff, 0x00, 0x00));
for (int i = 0; i < mMonth.length; i++) {
mRenderer.addXTextLabel(i, mMonth[i]);
}
// adding renderer to multiple renderer(chart)
mRenderer.addSeriesRenderer(renderer);
GraphicalView view = ChartFactory.getBarChartView(this, dataset,
mRenderer, Type.STACKED);
RelativeLayout layout = (RelativeLayout) findViewById(R.id.rlBarChart);
layout.addView(view, 0);
}
Hope this helps.

Bar chart shrink behaviour when scrolling horizontally with setInScroll enabled

I'm creating a dynamic bar charts using achartengine in my application. Bar charts are used to display weekly work data in hours and they are scrollable horizontally (each bar chart have its own view with width of screen). I've placed bar charts in HorizontallScrollView with infinity scroll and sticking enabled (by swapping views with each other) and when I'm scrolling to either left or right the bar charts shrinks to the side of screen instead of being scrolled out of screen like rest of views. I've found that I should enable setInScroll on renderer of my chart to get rid of this behaviour but sadly this doesn't work (chart shrinks with setInScroll set to true). I'm out of ideas how to fix that. Here's my renderer setup:
private static XYMultipleSeriesRenderer getRenderer(List<Integer> list, int[] weekdays)
{
float maxValue = 0;
for (Integer value : list){
if (value > maxValue){
maxValue = value;
}
}
NumberFormat formatter = new DecimalFormat("#' h'");
formatter.setMaximumFractionDigits(0);
maxValue = maxValue/60;
maxValue = maxValue + (float)(maxValue*0.2);
XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
XYSeriesRenderer seriesRenderer = new XYSeriesRenderer();
seriesRenderer.setColor(mContext.getResources().getColor(R.color.ActionBarBlue));
seriesRenderer.setChartValuesFormat(formatter);
seriesRenderer.setFillPoints(true);
seriesRenderer.setLineWidth(2);
seriesRenderer.setDisplayChartValues(true);
seriesRenderer.setChartValuesTextSize(12);
seriesRenderer.setChartValuesTextAlign(Paint.Align.RIGHT);
renderer.addSeriesRenderer(seriesRenderer);
for (int i=0; i < 7; i++){
renderer.addXTextLabel(i+1, mDays[i] + " " + weekdays[i]);
}
renderer.setBackgroundColor(mContext.getResources().getColor((R.color.White)));
renderer.setApplyBackgroundColor(true);
renderer.setPanEnabled(false);
renderer.setInScroll(true);
renderer.setMargins(new int[] {0, 0, 0, 0});
renderer.setAntialiasing(true);
renderer.setMarginsColor(mContext.getResources().getColor(R.color.White));
renderer.setShowLegend(false);
renderer.setXAxisMin(0.5);
renderer.setXAxisMax(7.5);
renderer.setYAxisMin(0);
renderer.setYAxisMax(maxValue);
renderer.setBarSpacing(0.5);
renderer.setShowGrid(true);
renderer.setGridColor(mContext.getResources().getColor(R.color.Gray));
renderer.setXLabelsColor(mContext.getResources().getColor((R.color.Black)));
renderer.setYLabelsColor(0, mContext.getResources().getColor((R.color.White)));
renderer.setLabelsTextSize(12);
renderer.setXLabels(0);
renderer.setYLabels(0);
return renderer;
}
Appears it was some kind of problem with Android Studio and java, not responding to any changes in code i made, rebooting PC worked.

How to make stacked bars have the same width in AChartEngine

I want to draw a bar chart with 2 stacked bars with AChartEngine, like in the SalesBarChart example. My Problem is, the bars with same X value don't have the same width, i.e. the larger bar is wider than the smaller bar, see the image below.
Source code:
renderer = new XYMultipleSeriesRenderer();
// Set chart parameters
renderer.setBarSpacing(0.5);
// Margin background color
renderer.setMarginsColor(Color.rgb(0xF3, 0xF3, 0xF3));
// Disable pan and zoom
renderer.setPanEnabled(false, false);
renderer.setZoomEnabled(false, false);
// Text sizes
renderer.setAxisTitleTextSize(16);
renderer.setChartTitleTextSize(20);
renderer.setLabelsTextSize(16);
renderer.setLegendTextSize(16);
// X axis
renderer.setXLabelsColor(Color.BLACK);
renderer.setXLabelsAlign(Align.RIGHT);
// TODO: adjust axis limits depending on time series
// Y axis
renderer.setYAxisMin(0);
renderer.setYAxisMax(200);
renderer.setYLabels(10);
renderer.setYLabelsColor(0, Color.BLACK);
renderer.setYLabelsAlign(Align.RIGHT);
// Configure renderer for normal and alarm time series
XYSeriesRenderer alarmRenderer = new XYSeriesRenderer();
alarmRenderer.setColor(Color.rgb(0xCC, 0x00, 0x00));
renderer.addSeriesRenderer(alarmRenderer);
XYSeriesRenderer normRenderer = new XYSeriesRenderer();
normRenderer.setColor(Color.rgb(0x99, 0xCC, 0x00));
renderer.addSeriesRenderer(normRenderer);
[...]
dataset = new XYMultipleSeriesDataset();
renderer.setChartTitle(items[which]);
// Dummy Data TODO: replace with real data
Random r = new Random();
int limit = 100;
normValues = new TimeSeries("Normal");
alarmValues = new TimeSeries("Alarm");
dataset.addSeries(alarmValues);
dataset.addSeries(normValues);
for (int i = 0; i < 100; i++) {
Date date = new Date(i*1000);
int value = 70+r.nextInt(60);
if (value <= limit) {
normValues.add(date, value);
} else {
normValues.add(date, 100);
alarmValues.add(date, value);
}
}
if (!init) {
trend.removeView(chart);
}
chart = ChartFactory.getBarChartView(getActivity(), dataset, renderer, Type.STACKED);
chart.setBackgroundColor(Color.TRANSPARENT);
chart.setLayoutParams(params);
chart.setPadding(6, 20, 6, 0);
trend.addView(chart, 0);
How can I achieve that both bars have the same width??
This happens when the 2 series have a different number of items. Please make sure that the series have the same length.

How can we fit the chart on screen?

I am using aChart Engine, Zoom in and out functionality in it moves the chart away from the screen.I want to keep the Chart fit to screen. Is there any way to keep the chart visible on screen i.e. always fit it to visible portion ??
I am using this method :
private XYMultipleSeriesRenderer getLineRenderer(int[] lineColor, PointStyle[] styles) {
XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
renderer.setAxesColor(Color.BLUE);
renderer.setAxisTitleTextSize(16);
renderer.setChartTitle("Time");
renderer.setChartTitleTextSize(15);
renderer.setFitLegend(true);
renderer.setPanEnabled(true, true);
renderer.setYLabels(6);
renderer.setMargins(new int[] { 20, 30, 15, 0 });
renderer.setZoomButtonsVisible(true);
renderer.setBarSpacing(10);
renderer.setShowGrid(true);
renderer.setYAxisMin(Common.min - 1);
renderer.setYAxisMax(Common.max + 1);
XYSeriesRenderer rendererSeries = new XYSeriesRenderer();
rendererSeries.setColor(Color.RED);
renderer.addSeriesRenderer(rendererSeries);
rendererSeries.setFillPoints(true);
rendererSeries.setLineWidth(3);
return renderer;
}
You can use two things,
Either desable the Zoom functionality
renderer.setZoomEnabled(false, false);
or, Set Limits of for the Zoom
renderer.setZoomLimits(arg0); // arg0 = new double[]{-20,20,-20,20}; anything you want
I find out the solution to my query
renderer.setPanEnabled(false);
renderer.setPanEnabled(false, false);
It works fine
You can do either:
renderer.setPanEnabled(false);
or
renderer.setPanLimits(limits);

Categories

Resources