I have two ImageViews inside a constraint layout. One on top and one on bottom. I want to move the bottom one onto the top one. Of course I know it doesn't change it's actual position which I am ok with. When I use TranslateAnimation to move to the specified coordinates the image goes down and to the right instead of moving up and to the right. Also when it moves to the right it is slightly off. I can use view.animate().y(getTop).x(getLeft); and it moves the image into the correct position but then it is stuck there. I can't get it to move back to its original like it would if fillAfter was false.
First I get the destination location
float x = playerOneCard.getLeft();
float y = playerOneCard.getTop();
This code moves the card to the correct location but does not reset it after being moved. I need it to essentially move there, go back to it's original place, and repeat as many times as the button is pressed.
playerOneCardMove.animate().x(x).y(y);
This code moves the image but down and towards the right no where close to lining up with the desired destination.
TranslateAnimation translateAnimation = new
TranslateAnimation(Animation.ABSOLUTE,x,Animation.ABSOLUTE,y);
translateAnimation.setDuration(500);
translateAnimation.setFillAfter(false);
playerOneCardMove.startAnimation(translateAnimation);
Figured it out. Since I was going from the absolute position of the first image the top left of that image is 0,0. So it was moving accordingly. Instead I measured the distance from the top of the image on the bottom to the top of the image above it and then moved it according to distance. I did the same for both x and y coordinates.
float distanceY = Math.abs(playerOneCardMove.getTop() - playerOneCard.getTop());
float distanceX = Math.abs(playerOneCard.getLeft() - playerOneCardMove.getLeft());
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.ABSOLUTE,distanceX ,Animation.ABSOLUTE,(distanceY) - (distanceY*2));
translateAnimation.setDuration(1000);
translateAnimation.setFillAfter(false);
playerOneCardMove.startAnimation(translateAnimation);
Hope this helps someone else.
Related
I have Relative layout with background #mipmap/arrow. I am adding this relative layout (On user touch) in another relative layout which is having ImageView (using imageRelativeLayout.addView(arrowRelativeLayout)).
Goal :
1) I want to add arrow on ImageView after onTouchEvent() to particular (x,y) position. (This is working perfectly)
2) After adding arrow, I want to move arrow's end Point or start Point as per user's touch
3) when user touch on arrow's end point then it should move to respective (x,y) position but start point should be fixed
4)when user touch on arrow's start point then it should move to resp. (x,y) position but end point should be fixed
Arrow Head is Start Point & Arrow tail is End Point
Please Help me
Thanks in advance
So add some invisible views and anchor them to the start end location of the arrows, when a user presses this move them to the new location and then update the image view.
It depends on your graphics if the arrow is edge to edge or corner to corner within the rect, i would suggest corner to corner then you just have to set the layout parameters with the correct top/left and bottom/right also Rotate / Flip it depending on your start end points, but you only need to rotate by 90,180,270 degrees.
This method will mean that your arrow head will be squashed or stretched, if you want you can include a seperate arrow head which uses the angle generated and rotates to this angle, anchoring with the end of the arrow line that you want.
I'm trying to move a view to the upper right corner of the screen, using ObjectAnimator.ofFloat(...) But, I'm not getting the results I expect. I'm getting the coordinates of the view beforehand, using ViewTreeListener, etc, and I already know the x value I need to offset from the end of the overall width. I can't get either dimension to move to where I want it. Relevant code:
Getting the starting coordinate; where the view currently is:
int[] userCoords = new int[]{0,0};
userControlLayout.getLocationInWindow(userCoords);
//also tried getLocationInScreen(userCoords); same result
userUpLeft = userCoords[0];
userUpTop = userCoords[1];
Surprisingly, I get the same value as userUpLeft (which is in screen coordinates, and not relative to parent) when I call userControlLayout.getLeft() I'd expect them to be different per my understanding of the docs. Anyway...
Constructing the ObjectAnimators:
//testXTranslate is a magic number of 390 that works; arrived at by trial. no idea why that
// value puts the view where I want it; can't find any correlation between the dimension
// and measurements I've got
ObjectAnimator translateX = ObjectAnimator.ofFloat(userControlLayout, "translationX",
testXTranslate);
//again, using another magic number of -410f puts me at the Y I want, but again, no idea //why; currently trying the two argument call, which I understand is from...to
//if userUpTop was derived using screen coordinates, then isn't it logical to assume that -//userUpTop would result in moving to Y 0, which is what I want? Doesn't happen
ObjectAnimator translateY = ObjectAnimator.ofFloat(userControlLayout, "translationY",
userUpTop, -(userUpTop));
My understanding is that the one arg call is equivalent to specifying the end coordinate you want to translate/move to, and the two arg version is starting at...ending at, or, from...to I've messed around with both and can't get there.
Clearly, I'm missing very fundamental knowledge, just trying to figure out what exactly that is. Any guidance much appreciated. Thanks.
First, userControlLayout.getLeft() is relative to the parent view. If this parent is aligned to the left edge of the screen, those values will match. For getTop() it's generally different simply because getLocationInWindow() returns absolute coordinates, which means that y = 0 is the very top left of the window -- i.e. behind the action bar.
Generally you want to translate the control relative to its parent (since it won't even be drawn if it moves outside those bounds). So supposing you want to position the control at (targetX, targetY), you should use:
int deltaX = targetX - button.getLeft();
int deltaY = targetY - button.getTop();
ObjectAnimator translateX = ObjectAnimator.ofFloat(button, "translationX", deltaX);
ObjectAnimator translateY = ObjectAnimator.ofFloat(button, "translationY", deltaY);
When you supply multiple values to an ObjectAnimator, you're indicating intermediate values in the animation. So in your case userUpTop, -userUpTop would cause the translation to go down first and then up. Remember that translation (as well as rotation and all the other transformations) is always relative to the original position.
I found out that the movement of an image between two point can be achieved with this simple code:
ImageView image_to_move = (ImageView) findViewById(R.id.image_to_move);
TranslateAnimation animation = new TranslateAnimation(50, 100, 50, 100);
animation.setDuration(5000);
image_to_move.startAnimation(animation);
The image is an ImageView set initially in position (0,0) inside a FrameLayout and the code move it from the point (50,50) to (100,100).
What if i have to move it on a path, made of several point, in the form of absolute coordinate (x,y)? For example, move from (50,50) to (75,75) then to (100,100)
There's a way to pass to the translating function an array of coordinate or i have simply to iterate the animation for every couple of points?
Btw, i saw that if i don't initially locate the image in (0,0) the function moves the image in a weird way, like the coordinate i give are not read as absolute. Am i missing something?
EDIT: The last thing happens when i pass as parameters to the TranslateAnimation something like "n92.getX()" where n92 is a button on my frame layout, from which position i want the animation to start.
DETAIL: Just to understand better the problem: I am implementing the animation of a point moving on a map, to show the user how to get from one point to another of a map. That's why i have absolute coordinate (the reachable points) that must be followed (you can't arrive from one point to another without following a precise path on the map)
to do so you need to Calculate the position on a quadratic bezier curve. try this answer it might be work for you
I have a custom drawn rectangle which i want to move in a circular path based on touch events.
It follows the direction of the touch for clockwise or anticlockwise movement but basically move in circular motion, as if moving on the edge of the circle.
My current thought process is as follows:
Based on the users current and previous x,y i shall find the angle in degrees and then move this rectangle by the same angle by re-drawing in the new position, just making sure that it moves on the edge of a circle.
But this leads to some confusion on the following:
1. how do i decide whether angle movement is clockwise or anti-clockwise.
2. I am not being able to figure out the math for this properly.
Would this be the best approach or is there a better idea for doing this?
Also, if this is the best approach, could someone please tell me the formula for calculating the angle by which i should move it while taking care of the clocking and anticlockwise ?
could someone please help?
please let me know if any more details are required.
Thanks
Steps
Here are a few steps in order to move your rectangle along a circle's rim when the user taps and holds to the side of the circle:
1. Obtain direction desired.
2. Obtain angle from current x and y coordinates.
3. Add direction (+1 if counterclockwise, -1 if clockwise) to angle.
4. Calculate new x and y coordinates.
5. Update/display rectangle.
Details
1. In pseudocode, direction = sign(Rectangle1.x - UsersFingerPosition.x). Here sign is a function returning -1 if the number was negative, 0 if it is 0, and 1 if it is positive. Note that sign(0) will only result when the user is on the exact x and y of your rectangle's location. In that case, the rectangle would not move (which should be good). In Java, the sign function is Math.signum().
2. To obtain the current angle use the following java code:
double angle = Math.toDegrees(Math.atan2(Circle.y-Rectangle1.y, Rectangle1.x-Circle.x));
Note the order of Circle.y-Rectangle.y and Rectangle.x...Circle.x. This is a result of the coordinate (0, 0) being in the top left corner instead of the center of the screen.
3. Simple enough, just add direction to angle. If desired, do something like
angle += direction*2; //So it will move more quickly
4. To get the new x and y coordinates of your rectangle, use the trigonometric functions sine and cosine:
Rectangle1.x = Math.cos(Math.toRadians(angle))*Circle.radius + Circle.x - Rectangle1.width;
Rectangle1.y = Math.sin(Math.toRadians(angle))*Circle.radius + Circle.y - Rectangle1.height;
(where Circle.x and Circle.y are the coordinates of the center of your circle and Circle.radius is naturally it's radius).
5. This one you'll have to take care of (or have already) :)!
Hope this helps you!
Steps
Here are a few steps in order to move your rectangle along a circle's rim:
1. Obtain finger position/Check that it's still dragging the rectangle.
2. Obtain angle from current x and y coordinates.
3. Calculate new x and y coordinates.
4. Update/display rectangle.
Details
1. This one is probably specific to your code, however, make sure that when the user starts dragging the rectangle, you set a variable like rectangleDragging to true. Before you run the next steps (in the code), check that rectangleDragging == true. Set it to false once the user lets go.
2. To obtain the current angle use the following java code:
double angle = Math.toDegrees(Math.atan2(Circle.y-Finger.y, Finger.x-Circle.x));
Note the order of Circle.y-Finger.y and Finger.x...Circle.x. This is a result of the coordinate (0, 0) being in the top left corner instead of the center of the screen.
3. To get the new x and y coordinates of your rectangle, use the trigonometric functions sine and cosine:
Rectangle1.x = Math.cos(Math.toRadians(angle))*Circle.radius + Circle.x - Rectangle1.width;
Rectangle1.y = Math.sin(Math.toRadians(angle))*Circle.radius + Circle.y - Rectangle1.height;
(where Circle.x and Circle.y are the coordinates of the center of your circle and Circle.radius is naturally it's radius). Subtracting the width and height of the rectangle should center it on the circle's border instead of placing the left, upper corner on the circle.
4. This one you'll have to take care of (or have already) :)!
Hope this helps you!
hi I'm working with the animations, I currently have 4 directional buttons, depending on which button I press, the image will move in that direction. My problem is so that the image goes beyond the edges of the screen, and I have no idea how to do it xD. For the animation use this ObjectAnimator objectAnimator= ObjectAnimator.ofFloat(IMG3, "translationX", Position_Start,Position_End);
Of course! All you need to do is get the size of the screen in pixels (see here). the top left corner of the screen will be (0,0) and the bottom right will be your output from one of the functions provided.
Then, all you need to do is get the position of your view (animation) using View.getLocationOnScreen() and/or getLocationInWindow() to get the top left corner and using View.getWidth() and View.getHeight() to get the size of your view.
The final step is to make sure that View.getLocationOnScreen() is never less than (0,0) and View.getLocationOnScreen() + (getWidth(),getHeight()) is always less than display.getSize(size), or whatever method you use to get screen size.