How to space out labels on Y-Axis aChartEngine Android - android

Good day, i have a slight issue. i have created my own Labels on the Y-Axis with the following code below, but they are so clustered together, How can i space them out?.
Here is my code:
renderer.setYLabels(0);
//value_value is an array which would use as the labels for the y axis
int value_size = value_value.length;
int m = 0;
//int add = value_size/10;
int add = largest_size/10; // largest_size is the biggest value in the array value_value
for(int i=0; i< 10; i++){
if(m > value_value.length){
break;
}
renderer.addYTextLabel((double)i, value_value[m].toString(), 1);
m+=add;
}
P.S: from the api docs, there is a 3rd parameter "int scale" which i thought would help me space out the margins but i never seem to use it correctly. if i put any value there, i get a NullPointerException. What does it really do and how to use it?
Any help will be highly appreciated. Thank you.
My Graph:

Adding custom labels can be tricky because you always have to make sure you are not overlapping them. You should add only as many as needed to avoid overlapping. You can also listen for pan and zoom events and update the custom labels accordingly.
The scale parameter is useful when you have multiple Y axis scales. If you don't have then you don't need to use the parameter.

Related

MPAndroidChart gradient line depending on dataset values

I'm currently working on a project using MPAndroidChart and i want to make a LineChart to represent data per hour. I need this chart to have gradient line depending on values on yAxis.
eg. In the graph above i want the line to change the color when yAxis values are >50.
I didn't find any solution to my problem, so any suggestions or examples are welcome
I've recently had to face the exact same problem, and the solution was to define a linear gradient and apply it as a shader, like this:
(Warning: You'll notice that the code looks funny, and that is because it is xamarin code (i.e: C#, not java nor kotlin), but you'll be able to translate it easily, mostly you have to change the PascalCase for camelCase, and change some properties into setters and getter or vice versa, just use your IDE's intellisense)
[set your line chart, add the dataset, etc]
...
var gradient = new LinearGradient(0f, 0f, 0f, 100f,
[your first color], [your second color],
Shader.TileMode.Clamp);
var paint = vh.Chart.Renderer.PaintRender;
paint.SetShader(gradient);
...
[set axis, labels, grid, etc]
...
lineChart.Invalidate(); //this is to refresh the chart on the screen, you may need it or not depending on your code
In the code above you just have to add your colors, and you may want to change the gradient direction (I'm using a vertical gradient here) by changing the 4 first floats when creating the linearGradient. One typical change is to set the y0 = 0 and y1 = the height of your chart, for example. You have to play with the values according to your layout.
The result for this code is something like:
Of course, I'm showing it with a repeated sample dataset, that's why you are seeing two cards with the same line.
UPDATE:
I understand what you want to achieve, and with the code above you can do it. You will need some calculations, of course, but you can set the "trigger" where the color starts to change at any Y coordinate you want.
For example, in this first picture, I've used the coordinates 0,0,0,100
(Please keep in mind that I'm showing you the last value in dp, but in the real code I am translating it to the equivalent in pixels according to the device's resolution. It is roughly the height of my chart)
And in the following image, I've changed it to 0,0,0,50:
As you can see, you have full control over how the gradient is shown just by changing the 4 values. (or, in my case, just one of them)
(You may notice that I've changed the colors as per my design, it has nothing to do with the threshold)
Lets say you are using for-loop to populate your data. In list you need to populate a list of colors for every value and then use lineDataSet.setColors(listOfColors).
List<Integer> listOfColors = new List<>();
for(i= 0; i<dataEntries.size(); i++){
//Logic for colors
if(i<= dataEntries.size()-1){ //Otherwise app will crash on last index
if(dataEntries.get(i+1).y > 50)
listOfColors.add(Color.GREEN);
else
listOfColors.add(Color.RED);
}
Then in the last
lineDataSet.setColors(listOfColors)
Hope, this will help you.

AChartEngine y-axis labels are cut

How do I know what margins to use in an AChartEngine chart to prevent the y-axis labels from being displayed outside the chart when it is set to fill a layout? Can I automatically resize the chart so that the y-axis labels always are visible, even if they contain more than 2-3 digits?
/Markus
You cannot do this automatically, but you can tweak the values until it looks good. You can also rotate the labels when you have several digits values.
This is what I used to deal with Y axis labels that can have differing numbers of digits. Find your max Y value, round it to an int, convert to string and then count the length of the string. The length of the string can be used to calculate a value for the Left margin.
//**** Find max y value of dataset
Ymax = getMaxValue(U_Limit);
if(Ymax < 10){
Ymax = 10;
}else{
Ymax = Ymax*1.1;
}
//**** Find int value of number of digits in max y value
int PLAY_FACTOR = text_label_size*.5 // you may have to play around with this value
int leftMargin = (Double.toString(Math.round(Ymax)).length())*PLAY_FACTOR;
int margins[] = { 26, leftMargin, botMargin, 14 }; // Top,Left,Bottom,Right
renderer.setMargins(margins);
Found a better solution, if you use setYLabelsVerticalPadding with a negative value you can move a little bit down the label... in this way the upper Y label will be visible no matter what.
Hope it helps.

Drawing on the android screen with a coordinate system

My question is probably going to be initially very confusing to read, so just bear with me. I'll start it off with a little preface for context:
Preface:
I have an app that will be using an array for path-finding from a map.
^That is very vague: There will be an array of characters, representing walls, stairs, etc., and there will be a function that finds the best path.
I want to display the path on the android screen.
There will be characters that are generated by the array function that represent the generated path (probably "x" or something).
Okay, to make it more clear: There will be a "path" of 'x's in an array. These 'x's represent the path that is going to show up on the Android screen.
My actual question:
How do I translate an 'x' in the array to displaying a line on the screen? I had the idea to use a for loop/if statement that checks if there is an 'x' and if there is, then to display a little red dot/line in a second array that represents the actual screen.
I was trying to find this, but it's such an awkward thing to type into google, so I finished my research with nothing.
Is there some sort of built-in android function that lets you assign different colours to different coordinates?
This is kind of what I want to appear on the screen. If this were the app, the blue would be represented by 'x's in the first array.
there could be several ways to achieve this effect of having a coordinate system mapping to a matrix that describes a path.
Depending on the size of the array and the frequency of update calls (it sounds like the path finding runs once with a single render after), it probably wouldn't be too expensive to just loop through. What I personally would do is start to look at how to draw on a canvas, get the screen size, and adjust the bounds accordingly.
Get screen dimensions in pixels - How to get screen dimensions
http://danielnadeau.blogspot.com/2012/01/android-canvas-beginners-tutorial.html - A nice tutorial on canvases
Once you can draw to a scaled canvas, it is simply a matter of running a loop that looks something like:
float scale_x = screen_width/columns;
float scale_y = screen_height/rows; //pixels per grid square
for( int x = 0; x < columns; x++)
for( int y = 0; y < rows; y++)
if( data[x][y] == 'x') drawRect(x*scale_x, y*scale_y, scale_x,scale_y) //if something found, draw a colored square

Achartengine: scolling and re-draw Pan. How can I do?

I'm using achartengine and I show a ghraph where on the x axis are putted the last 30 days starting by the current date and on the y axis some values from 15 to 0. In my code I used
for(int i=0; i<= array of value to be inserted i++){
.....
aRenderer.addXTextLabel(//value I want is showd on x axis);
.....
}
aRenderer.setXAxisMin(dateMin);
aRenderer.setXAxisMax(adateMax);
aRenderer.setXLabels(0);
Now given that I customized my x labels, when I scroll on the right and on the left, the other labesl don't appeare. So I thought of create a new class that implements PanLinstener and in the panApplied() redraw the labels when I scroll the panel.
Someone has a better idea to to this?
This is what I obtain when I scroll to left from right:
I opted for implementing a PanLinstener, re-drawing the graphs in the panApplied() method.
Under the panApplied() method you will have to rebuild the custom labels.
You will probably need to know the X axis range: renderer.getXAxixMin() and renderer.getXAxisMax() and add new custom labels between this interval.

How do I set grid depth\z-index of achartengine in Android?

Still having a great time fiddling with aChartEngine, but I have come to a point where I could some help.
I'm looking to change the depth or z-index of the grid of a chart. But so far I haven't found any options in both the regular documentation as in the source to set the this.
Does anyone has a tip or solution regarding the grids in aChartEngine?
Thanks for your help!
I guess nobody has this issue, but just in case you might wonder how to change the depth of the grids in aChartEngine, I'll write it down here.
By default all the grids of aChartEngine are drawn on top of the graph itself. This happens in the public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint) of the XYChart.java class.
Both the labels and grids are drawn in the same conditional, which checks whether (showLabels == true || showGrid == true)
First thing you might want to do is split the drawing of the labels and grid. Here's what I did:
Copy the whole conditional which checks for labels and grid, including the declaration of the 3 booleans showLabels, showGrid and showCustomTextGrid.
Paste it below boolean hasValues = false; (set this to true)
You'll have some errors in the class now, because of double declarations. Fix that later.
In the conditional you just pasted, remove the code to draw the labels. It's easy to find, since it starts with if (showLabels). Below the conditional set hasValues = false;
In the original conditional, remove the code to draw the grid. It's easy to find, since it starts with if (showGrid)
Now get rid of the double declarations, by setting the booleans showLabels, showGrid and showCustomTextGrid, or just use the old ones.
All the errors should be gone now, test your app. The labels and grid are now separated and the grid is shown behind your graph instead on top of it.
Hope it helps you.
Cheers!

Categories

Resources