Rotating a view on Android issue - android

I have been stuck on quite an irritating problem for a number of days now.
To describe the problem; I essentially have a issue when I perform a rotation on a view which is part of a larger view, then I display a fragment on top of this view, and then hide this fragment returning to the original view.
The view maintains its rotation but is placed above and to the right of where it should be.
In the XML layout I have set the view to be centered in the parent, and sure enough on startup everything is where its supposed to be.
While the view is rotating and the main view is visible (it is essentially a compass) everything works as intended
If I do not rotate the view, then show the fragment followed by hiding it it stays where it was meant to be without issue, so clearly the act of rotating it and then displaying something over it is causing a problem.
If I continue to rotate the view after it has moved out of position, it snaps back into its centered position and all is well - how can I ensure the view to always remain where its suppose to be?!?
For reference I am calling the rotation method like so:
RotateAnimation rotate = new RotateAnimation(PREVOIUS_ROTATION_AMOUNT, NEW_ROTATION, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(980);
rotate.setRepeatCount(0);
rotate.setFillAfter(true);
compassView.startAnimation(rotate);

This code should do what you're expecting:
compassView.setPivotX(compassView.getMeasuredWidth() / 2);
compassView.setPivotY(compassView.getMeasuredHeight() / 2);
compassView.animate().rotation(NEW_ROTATION).setDuration(980);

Related

RotateAnimation behaves weird after changing the position of a View

I am using RotateAnimation to rotate the imageView to -30 degrees. And it works good. Now I change the position of the view by setting different values for X and Y. All good until now.
Now when I perform the same RotateAnimation again to this view after the position changed, it works weird (see the video link below) and I cannot find the reason. I have tried a lot but without success. It seems like related to the pivotX and pivotY after changing the position but I cannot find the actual cause.
Code for RotateAnimation
final RotateAnimation rotateAnim = new RotateAnimation(0f, -30f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 1f);
rotateAnim.setDuration(2000);
rotateAnim.setFillAfter(false);
ivFace.startAnimation(rotateAnim);
Code of changing the position of an imageview
ivFace.setX(300);
ivFace.setY(200);
Here I am posting the video also for better understanding
https://www.youtube.com/watch?v=uVWlrTNDKCM
Looks like the RotationAnimation is still rotating around the 'old' view position, probably because it is 'final' and thats why it is tied to the Views 'old' position the moment it is created. You could create a new RotationAnimation for every position change, which might solve the issue, although I would suggest using ViewPropertyAnimator and/or ObjectAnimator for both, translating your View to another position and rotating it.

Android: negative coordinates in ViewGroup and touch rectangles

I come from an ActionScript/Flash/AIR background and I'm new to the Android View hierarchy. Given that, I found something very odd about ViewGroup and it's coordinate system.
Let's say we have the following parent/child relationship inside the main Activity View which extends RelativeView (or basically some group layout that allows absolute coordinates and scale):
circle1 = new ImageView(context);
circle1.setImageBitmap(...);
circle2 = new ImageView(context);
circle2.setImageBitmap(...);
cont = new RelativeView(context);
cont.addView(circle1);
cont.addView(circle2);
this.addView(cont);
The idea is to create a container which is centered on the main view and to center two circles inside of the container. This allows the container to be animated, grouping the two circles.
cont.setX(getWidth() / 2);
cont.setY(getHeight() / 2);
circle1.setX(-circle1.getWidth() / 2);
circle1.setY(-circle1.getHeight() / 2);
circle2.setX(-circle2.getWidth() / 2);
circle2.setY(-circle2.getHeight() / 2);
Doing negative coordinates inside a ViewGroup, I immediately noticed that 'cont' clips them at the [0, 0] coordinate and cont.setClipChildren(false); has to be called. I'm guessing this is a bad idea, because it looks like a optimization for the invalidate() area. After disabling the clipping, the result renders as expected, but there is another problem:
illustration
Adding a touch event listener to circle2 returns a bogus touch rectangle (marked in purple) instead of the expected one (marked in cyan) which should be staring at the negative [X, Y] offset of circle2. The resulting rectangle starts at [0, 0] of 'cont' and ends at [circle2X + circle2W, circle2Y + circle2H] as if it's clipped at [0, 0] of 'cont'.
I know that you can solve the issue by not using negative coordinates, but that's not really a good solution if you are porting from ActionScript where negative coordinates make perfect sense (as in any real world coordinate system) and touch rectangles are calculated correctly in the DisplayObjectContainer class.
So what other solutions are there?
Should a custom ViewGroup class be created and what has to be done there?
Is there a magical setting which can allow touch rectangles of children Views not to be clipped at [0, 0] of the parent ViewGroup?
Something else?
Thanks.
You can use View#scrollTo to move the origin so that your content is shown entirely within the View's bounding rect.
Many things in the Android UI toolkit rely on the measured and laid out bounds of Views being accurate. In general you don't want to go against the grain here.

TouchUtils.dragViewToX will only scroll in one direction

I can easily use the following code to scroll the view to the left using
TouchUtils.dragViewToX(this, myView, Gravity.LEFT, -1000);
It will even just sit there for a second if it can't scroll anymore, like it's still trying to, which is the expected behavior, so the contents of the view shouldn't be the issue.
But if I do the opposite, it acts as though it's not even there.
TouchUtils.dragViewToX(this, myView, Gravity.LEFT, 1000);
It doesn't even pause for a second to simulate the dragging like the other one will no matter what. It even returns the propper pixel value for distance covered! Why will it only listen to this function when it's supplied with a negative value? Why will it not drag in the opposite direction?
It's not even a positive/negative issue, it will scroll to the left if I supply a positive value and a different Gravity (like RIGHT or END), but no matter what it won't scroll to the right.
First of all, dragViewToX will try to drag the view you specify to the X-coordinate you specify.
The Gravity field specifies which part of the view is to be dragged.
So I'd suggest you use the rect values rather that using hard coded coordinates so that the test will work independent of the device specification. Here's a sample code.
View view = sListView.findViewById(R.id.foo);
Rect rect = new Rect();
view.getHitRect(rect);
TouchUtils.dragViewToX(this, view, Gravity.CENTER, rect.left); // To drag left. Make sure the view is to the right of rect.left
TouchUtils.dragViewToX(this, view, Gravity.CENTER, rect.right); // To drag left. Make sure the view is to the left of rect.right
The only thing that is wrong with your code is that the value 1000 is already out of the screen and therefore there is no where to drag to :)

Android - Rotate Admob view 90 degrees?

I have been working 2 days to make Admob view displays vertically on my landscape game, the problem seemed to be straightforward, just rotate the view 90 degrees. The first try was to call setRotation(90), I had a crash on my 2.3.4 device because the method is not available untill Android 11. The second try was to use rotation animation, the view did rotate but it get clipped to its original bounds and furthermore it accepts touches as if it was not rotated :(. Finally I found a way to solve the clipped view problem, just call setLayoutParams(width, height) - with width and height large enought, on all the child view of admob view. The problem of touches still unresolved :)
I'm very frustrated, why Android needs a very complex solution for a very simple problem ? In iOS, I just need to apply a rotation transformation to the view and nothing more !
Please help me !
Any suggestion are welcome :)
RotateAnimation rotate = new RotateAnimation(0, 90, admobView.getWidth() / 2, admobView.getHeight() / 2);
rotate.setDuration(500);
rotate.setRepeatCount(0);
rotate.setFillAfter(true);
admobView.startAnimation(rotate);

Android Animate view from off screen not working

I have a view that is positioned totally off screen and I am trying to animate it onto the screen.
When I call:
view.startAnimation(tA);
nothing happens, tA.initialize and tA.applyTransformation never get called.
If I move the view so that any part of it is visible before I start the animation, then the animation works correctly.
What is preventing a view from being animated when it is positioned off the parent View?
It's my understanding from researching the same problem that Android Animations do not do well when provided with offscreen coordinates for their start or finish.
There is some dialog on the Android forums about this bug having been addressed but I'm still experiencing problems on 4.2.
Edit:
On second thought, I just ran across this answer and it provides a working alternative if you can use the newer APIs (ObjectAnimator).
View view = this;
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "y", 0, 100);
anim.setDuration(super.animationDuration());
anim.start();
Where the properties of ObjectAnimator.ofFloat(view, "y", 0, 100); are
ObjectAnimator.ofFloat(Object objBeingAnimated, String propertyBeingAnimated, float startValue, float endValue)
I found this answer using ValueAnimator to modify the MarginLayoutParams.topMargin (in my case) in onAnimationUpdate(), which fixed the issue. My View starts out with its margin set so that the View is off screen.
The ObjectAnimator approach was promising but did not work for me, it had the same cutoff issue for off-screen views that I got with TranslateAnimation.

Categories

Resources