I have a piece of code where I am displaying some pins (Button with an image) on an image (full screen ImageView). (You can assume that all the pins are created dynamically and have a random position). The requirement is that those pins should not overlap. For each pin created I am checking if it overlaps with any of the other previously created pins.
To do that I am trying to get the Rect of those pins and check if they overlap using Rect.intersects().
The issue is that I cannot use functions like getRight(), getTop(), getWidth(), getHeight() before the view is actually displayed. They all return 0. So I cannot get the correct data for the rectangles.
I tried to put the code in different callbacks like onWindowFocusChanged() or onResume() but I still got the same issue, all dimensions/positions return 0.
I am looking for a solution/advice regarding this problem. How to get the correct positions and dimensions before the pins are displayed ?
I looked at View.measure(), it seems I can get some values using getMeasuredWidth() and getMeasuredHeight() but getRight() and getTop() still return 0.
Add invisible rect first and check the position then move this position as per requirements and the make this visible. This will do the trick.
Related
I'm attempting to use a SurfaceView to manually draw some borders that snake around a few UI views (for practice) and I'm using View.getX(), getY(), getHeight(), and getWidth() to make sure that the lines are drawn correctly on different screens.
The problem is that the borders are being drawn offset from where they need to be. The relative placement of the lines is correct, but they just need to be shifted down and to the right.
I investigated the problem by using the Android Device Monitor to get the "Layout" > locationOnScreen_x and the "Drawing" > x variables and noticed that they were different. locationOnScreen_x shows the correct value of 70, while x shows 0.0. I assume that getX() returns the x value, which I apparently don't want.
My question then is two-part:
How can I programatically retrieve locationOnScreen_x instead?
What factors can cause x to differ from locationOnScreen_x?
I finally solved my problem by realizing that getX() returns the X value relative to the parent View and not relative to the device's screen.
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 find that the unit of the coordinate system of Canvas is different from that of screen.
For example in my case as below:
For one particular point, its on-screen coordinate obtained from ImageView.getX() and ImageView.getY() is (336, 578).
Then by trial and error, I draw a dot on the Canvas so that this dot falls EXACTLY the same position as the ImageView. I called canvas.drawCircle(330, 440, radius, paint); to achieve this.
Here comes the question:
Why would the 2 coordinates, (336, 578) and (330, 440), different?
Is it because the screen and the canvas use different units?
Is it an issue regarding pixel, dp and all that?
You could try converting to and from window coordinates using View.getLocationInWindow this way you'll always be sure you are using the same coordinates system.
Coordinates of ImageView.getX an Y are relative to the parent. Canvas coordinates are relative to the view. This could cause the differences
Edit:
I assume in one place you get the coordinates of the view (using getX and getY). Convert these to window coordinates. Call these viewXY[].
When you need to use them, to draw in your canvas, also convert the top and left coordinates to window coordinates. We call these canvasXY[].
Now, the X position to draw at would be viewXY[0] - canvasXY[0], and the Y position would be viewXY[1] - canvasXY[1].
A view's position co-ordinates are always relative to it's parent. It's like saying, where with respect to it's parent is this view placed.
There in another thing, screen Co-ordinate. This says where with respect to the window top/left (think actual physical screen) is this object placed. This can be obtained through View.getLocationOnScreen.
If you want to compare two locations, they will only be equivalent if the parent view of both these locations is same or you're using absolute screen co-ordinates. Otherwise, you'll only get results that "seem" different.
If you want to unify the two either take them to a common parent or use absolute co-ordinates.
I am working on a side scrolling game for Android like Mario or Megaman and I am having an extremely weird error that I cannot find any information on anywhere. I have my main character(an ImageView) on the screen on top of a relative view. The view only has the imageview and 3 buttons on the bottom of the screen. I move the image around the screen using setX() and setY() and the image moves correctly in the X direction, but for some reason the Y coordinates are always off by 32. Nowhere in my code is the Y value changed except for when it is initialized, and the getY() is always 32 higher than the value I assigned to it. The X value is fine. I am running it in Android 4.1. The only thing that I can think of is it being some sort of back end alignment protocol, but I can't find any information on it. Does anyone know what is causing this weird issue?
I think that the activity loads with the title bar, and then the title bar gets removed at some point shortly thereafter, so the problem might be initializing the Y value at a time when the title bar still exists. Maybe try initializing the Y value on the first time through your onDraw function, like so:
public void Draw(Canvas canvas) {
if (!yHasBeenInitialized) {
initializeY();
yHasBeenInitialized = true;
}
...
}
I have a MapView, with various markers on it. On entering the MapActivity the first time, I set the bounds of drawables set on the markers, and everything appears fine. The markers and shadows all appear correctly. But when I click over to another activity, and return, the shadows, or the markers are no longer bound correctly. Sometimes its only some of the markers that are affected. Can anyone tell me what is going on here? Here is some code. Below is where I set the bounds on the marker drawable:
InputStream is = assetManager.open(imageName);
drawable = Drawable.createFromStream(is, null);
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
drawable.setBounds(-width / 2, -height, width - (width / 2), 0);
And here is how I create/add the overlay item to the map:
GeoPoint point = createGeoPoint(lat, lon);
OverlayItem overlayItem = new OverlayItem(point, character.get_id(), "");
Drawable image = drawable;
overlayItem.setMarker(image);
itemizedOverlay.addOverlay(overlayItem);
From what I can tell, the overlays are not being re-added to the map, this is simply a redraw after an onResume() event. Any ideas?
Update: I've actually figured out, only images of the type tapped move, and its not the shadow, but the image that moves. So, of there are x images of type A, and y images of type B, and I tap on any image of type A, all images of type A are misaligned with their shadows when I return to the MapActivity, while all images of type B are still properly aligned.
Another update: I am outputting the bounds to the log, and see that the bounds are changing after returning to the map screen. When the marker is initially added, its bounds are:
[Rect(-25, -48 - 25, 1)]
But when returning to the map screen, the bounds have changed to:
[Rect(0, 0 - 50, 49)]
...why would this be?
Yet another update: I have a workaround... but I would still like an answer as to why this is happening. The workaround is to override the draw method, and set the bounds (to center bottom) whenever the draw method is called. Here is the code:
#Override
public void draw(Canvas canvas) {
int dWidth = getIntrinsicWidth();
int dHeight = getIntrinsicHeight();
setBounds(-dWidth / 2, -dHeight, dWidth / 2, 0);
super.draw(canvas);
}
I found out what the problem was. You can see from the code in the question, I am reading in BitmapDrawables from an InputStream. To reduce waste, I put all images created in a flyweight and reuse them when I can. That means, when I put 3 'sunshines' on the map, all three are based on the same image. In addition, when I place them on the map via an ItemizedOverlay, I am calling boundCenterBottom() so the shadow will display in the correct place.
When I open a different Activity, that Activity has an ImageView that I was populating with the same image. Turns out, that ImageView must have been resetting the bounds. I know this because, after overriding the draw() method, and setting the bounds on every draw, I was no longer able to see the images in the ImageViews. When I comment out the overridden draw() method, I am able to see the images in the ImageViews, but the images are shifted when I return to the map. This tells me that adding the image to the ImageView must be updating the bounds.
My solution is to create two distinct images for each image type; one for the map, and one for the ImageViews on the other Activities. I can still put them in the flyweight, but they have separate keys so multiple image instances can exist for the same image.
Hope this helps someone. I know there was another question of StackOverflow about this, but I can't find it to link to or to answer.