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;
}
...
}
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 trying to animate alpha of an Android view (two animations, both fade in and fade out). It all works fine if the view's alpha is initially 1, by default. However, I want that view to be transparent initially, hence I've set it's alpha to zero:
indicatorContainer.setAlpha(0);
Now, the animations won't work. It will never become visible. If I comment out that line, the view is initially displayed (which I don't want), but my animations works fine when I invoke them. I though it's something trivial but apparently it's not. What am I doing wrong?
UPDATE: I've also tried a floating point 0f instead of integer 0 after reading some API changes involving the setAlpha method, thinking that my call may be calling the incorrect overload, but nothing changed.
Try something like this:
mRelativeLayout.setAlpha(0f);
mRelativeLayout.animate().alpha(1f).setDuration(500).setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mRelativeLayout.setVisibility(View.VISIBLE);
//OR
mRelativeLayout.setAlpha(1f);
}
});
I faced same issue where indicatorContainer is ImageButton.
Below code fixes this very, very annoying issue...
// XXX: Does not work if just 0. It calls `ImageView#setAlpha(int)` deprecated method.
indicatorContainer.setAlpha(0.0f);
ViewCompat.animate(indicatorContainer).alpha(1);
One can try following, a more simple way:
view.animate().alpha(1).setDuration(ANIMATION_DURATION);
This might be irrelevant to the OP but I thought I'd share it regardless as it might help someone out in the future.
Please be aware that if you're initial animation combines animate().alpha(0.0f) with a manipulation of the View's Y or X-axis translation (e.g. animate().translationYBy(500) you have to reset this property before fading back in (using animate().alpha(1.0f).
I came across this SO post thinking that setting alpha back to 1.0f was failing when in actual fact it was still working as it should, but the animation was occurring off screen because I hadn't reset my Y-Axis translation (Homer Simpson *doh* moment).
Handily, to easily resolve this issue, you can add a AnimatorEndListener to your animation for when it finishes (as #Nikhil Verma mentioned above) where you can add a single line of code to reset the X/Y-axis translation.
In the scenario I faced I wanted the animation to float down and fade out so adjusted the Y-axis & alpha accordingly. After it had floated and faded I set a Listener to reset the Y axis translation like so:
loadingMask.animate().translationYBy(500); //starts animation by moving it down the screen
loadingMask.animate().alpha(0.0f) //fades out
.setDuration(1500) //over 1.5s
.setListener(new AnimatorEndListener() { //when animation completes
#Override
public void onAnimationEnd(Animator animation) {
loadingMask.setTranslationY(0); //reset the y axis translation
}
});
Now, when I want the animation to repeat again, I can set the alpha of my View to 1.0f and it works as intended.
Here's how I was able to kinda solve for this - not particularly elegant, but manageable:
Set the view to the initial alpha you want 0.0f or otherwise.
When the event occurs where you need the view to have more (or less) visibility/alpha - eg, right before you start an animation - at that point you can update the alpha and then run the animation on the view
I'm still getting some choppiness when the animation repeats, but this approach might work for scenarios where the animation is not repeated
I'm simply trying to drag a sprite around using my finger. I'm doing this by detecting the distance the finger that is touching the screen has moved by and then moving the sprite by the same amount.
This is an openGL ES 2.0 app, so my rendering and logic updating takes place on my GL Rendering thread, and obviously touch events are captured on the UI thread.
So, my setup is something like this:
UI Thread
case MotionEvent.ACTION_MOVE: {
movedByX = event.getX()-oldXPosition;
movedByY = event.getY()-oldYPosition;
oldXPosition = event.getX();
oldYPosition = event.getY();
break;
}
GL Rendering thread
Rendering
#Override
public void render() {
drawSprite(testSprite); //Draws using the sprites' internal x and y coordinates
}
logic update
#Override
public void updateLogic() {
testSprite.x+=movedByX; //Update the sprite's X position
testSprite.y+=movedByY; //Update the sprite's Y position
}
The issue
If one drags the sprite around the screen for a while, and then stops. The resting point of the finger relative to the sprite is not the same as it was when the finger initially went down. Take for a example a circlar sprite like so. The blue circle is the sprite and the red dot represents the finger/pointer.
So as you can see, it doesn't quite work as expected and I'm not sure why.
I had a similar question in previously in which I 'worked around' the problem by initially grabbing the X and Y in ACTION_MOVE (onTouchEvent/UI Thread) as I am above, but then in my updateLogic method, I make a copy of it and work out the 'moveByY' amount there before applying it to my sprite's position.
Doing this effectively solved the problem of the finger 'wandering' - but - it makes the movement of the sprite very choppy, therefore I can't use this solution.
I think this choppiness may be because the rendering thread sometimes runs twice without the UI thread running, therefore, even though the finger has moved, the logic is still using the version it has because onTouch hasn't been able to capture to actual most up to date finger position. But I'm not 100% sure.
If I simply update my sprite's positionin my UI thread, (again, in ACTION_MOVE) - again, I get very choppy movement but the pointer position does remain correct).
So, I need to keep the smooth movement that I get from the method outlined at the top of the question, but I need to know why the moveBy amount is causing the sprite to wander from the finger.
Other Notes
I need to move the sprite using a the difference between the finger's old and current positions, and not simply draw the sprite at the finger's current position because this will eventually become part of a 'scrollable' menu system.
All of my variables are declared as 'private float volatile' and my onTouchEvent and updateLogic methods are synchronised.
i dont know if its a typo
#Override
public void updateLogic() {
testSprite.x+=movedByX; //Update the sprite's X position
testSprite.x+=movedByY; //Update the sprite's Y position
}
but you set testsprite.x both times
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 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.