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!
Related
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.
Suppose I have six points drawn in a Canvas along the circumference of a circle, in the pattern of a hexagon.
I want to simultaneously move and re-draw each of these six points in a small circular path - for example, each point moves along the circumference of a circle with 1/10th the radius of the larger circle.
I'm a little lost on how to do this with Canvas and onDraw and I don't know if better solutions exist. How would you do this?
Some answers have at least pointed me toward this which shows how a point might move along a circular path, but I don't know how to implement it for this situation:
for (double t = 0; t < 2*Pi; t += 0.01)
{
x = R*cos(t) + x_0;
y = R*sin(t) + y_0;
}
Thank you!
Here's one approach:
Start with a custom view that extends View and overrides onDraw. You are on the right track with using the drawing functions of Canvas.
Give your custom view a field to hold the current angle:
private float mTheta;
Then add a method like:
public void setTheta(float radians) {
mTheta = radians;
invalidate();
}
Then in onDraw, use the current value of mTheta to calculate the position of your points.
Of course, with the custom view you might need to handle sizing with an onMeasure override and possibly some layout with an onLayout override. If you set the dimensions of the view to an absolute dp value, the default behavior should work for you.
Doing it this way will set you up to override onTouch and allow user interaction to move the graphics, or use a ValueAnimator to cycle from 0 to 2π calling setTheta from within your AnimatorUpdateListener.
Put some code together and when you get stuck, post another question. If you add a comment to this answer with a link to the new question, I'll take a look at it.
I am using CCTMXTiledMap on cocos2dx-2.2, I created and added the tiled map like this:
// TileMap
CCTMXTiledMap *m_pTileMap = CCTMXTiledMap::create("tilesets/my-isometric-small.tmx");
float fPosX = m_pTileMap->getPositionX();
float fPosY = m_pTileMap->getPositionY();
CCLOG( "TileMapPos: %f, %f", fPosX, fPosY );
this->addChild(m_pTileMap);
The tiled map are created and rendered successfully, but out of position. I use CCTMXTiledMap::getPosition, CCTMXLayer::positionAt, and also examine the CCSprite that I get from CCTMXLayer::tileAt... all of them are returning the correct value based on cocos2d screen coordinate { (0, 0) from bottom left and increasing upward and rightward } However, when viewed on the screen, there is always a slight offset and I can't get where it come from. All the m_obOffsetPosition are confirmed to be zero...
By correct value, I mean the tiles are positioned in the pink area (I getPosition from each of the tile, create CCSprite for each, setPosition of each tile and add it to the screen... They show up in the pink area)
Image supposed to be positioned at shady pink boxes, but instead positioned in the blue area (the entire blue sea is the whole map)
Any ideas are highly appreciated... Thanks!!
After wasting days trying to dissect tilemap_parallax_nodes in cocos2d-x, finally I figured out the culprit... it is the Layer Property cc_vertexz that cause it to be rendered off position. I haven't got the time to figure out how and why it works that way and since I'm not going to use it anyway (I just need flat, single layer, thus no need z order etc), so I just remove that property from all of my Layers and the problem is gone..
Hope it helps someone... Thanks!
I am trying to check collisions between two arrays, one of moving rectangles and the other of stationery boundaries (trying to get the rectangles to bounce off the walls).
The problem is that I wrote a nested for loop that seems to work for 2 out of 4 boundaries. Is my loop not reaching all possible combinations?
Here is my loop:
for(int n=0;n<_f;n++){
for(int m=0;m<_b;m++){
if(farr[n].inter(barr[m]))
farr[n].setD();
}
}
_f counts the moving rectangles (starts at 0 and increases after each one is added) and _b counts the boundaries. The inter() is a method I am using to detect collisions and it has worked in all other parts of my program.
Any help would be greatly appreciated,
Thanks in advace!!!
public boolean inter(Rect rect){
if(Rect.intersects(rect, rec))
return true;
else
return false;
}
The setD() method:
public void setD(){
if(_d==0)
_d=2;
if(_d==1)
_d=3;
if(_d==2)
_d=0;
if(_d==3)
_d=1;
}
The move method where _d is used:
public void moveF(){
if(_d==0){_l+=_s;_r+=_s;}
if(_d==1){_t+=_s;_b+=_s;}
if(_d==2){_l-=_s;_r-=_s;}
if(_d==3){_t-=_s;_b-=_s;}
}
_l is left side, _t is top, _r is right, and _b is bottom, and _s is how many pixels it moves per iteration(set to 1 in all cases)
Assuming _f, _b, farr, and barr do not change during the execution of the loop, your loop checks all combinations exactly once. So how is it that you "check some collisions twice"? Does setD() do something sneaky? Do you mean that once a rectangle collides there is no need to check more boundaries? If so, that can be fixed with a simple break statement. Otherwise, there likely is a problem with your inter() method, independent as to whether or not it appears to work elsewhere. Can you post your inter implementation?
There is a possibility of another problem, that of assuming continuous properties in a discrete space. As my amazing ascii art (titled: ball and wall) skills demonstrate...
Frame 1:
o__|_
Frame 2:
_o_|_
Frame 3:
__o|_
Frame 4:
___|o
Notice that the ball passed through the wall! In no frame did the ball intersect the wall. This happens if your distance moved per frame can be roughly the same or larger than the characteristic size of your moving object. This is difficult to check for with a simple intersection check. You actually need to check the path that the ball occupied between frames.
If your rectangles and barriers are oriented without rotation, this is still a fairly easy check. Use the bounding rectangle of the moving rectangle between the two frames and intersect that with the barriers.
Other ideas:
You are double colliding, switching the direction twice.
Your rectangles are in two different coordinate spaces.
Some other thread is screwing with your rects.
But basically, your code looks good. How many rectangles do you have? Can you make them distinct colors? Then, in your loop, when you collide, call setD and output the color of the rectangle that collided, and where it was. Then, when you notice a problem, kill the code and look at the output. If you see two collisions in a row (causing the rect to switch directions twice), you'll have caught your bug. Outputting the coordinates might also help, on the off chance that you are in two different coordinate spaces.
If it's a threading issue, then it's time to brush up on critical sections.
Found your mistake:
public void setD(){
if(_d==0)
_d=2;
if(_d==1)
_d=3;
if(_d==2)
_d=0;
if(_d==3)
_d=1;
}
Each of these needs to be else if, otherwise you update 0 to become 2 and then 2 to become 0 in the same call.
I asked this question once before, but didn't get any good feedback, so I'm posting it again to try to get more help
Ok, I'm making an app with this kind of of disk in it: http://dl.dropbox.com/u/8051037/disk_full.png
I have the two rings as separate images, but I need to figure out a way to position them like they are in the image, first off. I'm not great at figuring out layouts, so I don't really know where to start with that.
Also, I need each section defined by the black lines to be a different imagebutton. I've been everywhere looking for an answer to this, but no one's been able to help me so far.
Thanks for any help, been stuck on this problem for a few MONTHS now!
EDIT: To help make my problem a bit more clear, I'll fully explain what I'm doing. I'm making a launcher modification to make it kinda look like Tony Stark's phone from Iron Man 2, like this: http://perceptionnyc.com/sites/default/files/D_01_PDA_flat_01.jpg.
(Original question: How make one image into multiple buttons and some other stuff)
Your best best would be to create the image as a single view, override onTouchEvent() method, and call .getX() and .getY() on the event. Then you can determine where was clicked with some simple math.
This will result in a much better solution than trying to create multiple overlapping views and non-rectangular buttons.
edit:
Given (x, y) you can calculate where the click was using the Pythagorean theorem to get the length of the hypotenuse (for which circle was clicked) and get the angle using tan-1(opp/adj) (for which pie slice was clicked).
FYI, the (x,y) noted in the picture would actually be the respective difference from the center of the image, NOT the values of getX() and getY() directly.
Here is an example of similar code being used for a circular color picker in ADW.Launcher.
Do what Jake said. Try starting out something like this:
class Disk extends ImageView {
public Disk(Context context, AttributeSet attrs) {
super(context, attrs);
}
public boolean onTouchEvent (MotionEvent event) {
double x = event.getX() - getWidth() / 2.0;
double y = - ( event.getY() - getHeight() / 2.0);
// Compare this to the radii that mark the rings
double distFromOrig = Math.sqrt( x*x + y*y );
// Compare this to the angles of your slices (in radians)
double angle = Math.atan2(y, x);
return true;
}
}
Then put it in a view like this:
<view class="package.name.goes.here.Disk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/disk_full">
</view>
The downside is that there's no immediate visual feedback on which section the user selected.
Try using an image map, I think you can make two circles with different radii and depending on the order, one (the inner) will be on top of the other.
working JSfiddle example http://jsfiddle.net/mazlix/wksZq/
I just read your older post, in this case I recommend what the above user posted about using .getX() .getY(), you can just make one image with all the animations you want or two with the smaller inner circle image having transparency, to set them both exactly where you want (on top of eachother) just make sure you use position:absolute