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.
Related
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.
I want to rotate a simple imageview which has an elevation of 5dp.
animRotate=ObjectAnimator.ofFloat(imgProgress, "rotationY", 0, 360);
animRotate.setDuration(ANIM_DURATION);
animRotate.setRepeatCount(5);
animRotate.start();
The animation for the above code is smooth if the android:elevation value for the ImageView is not set in the layout file. But when i set the elevation, the animation becomes jerky.
Can someone please suggest a fix?
Maybe the reason is that you create and run animatuion at once. As docs say, it is better first to init your animation
//OnCreate
animRotate=ObjectAnimator.ofFloat(imgProgress, "rotationY", 0, 360);
animRotate.setDuration(ANIM_DURATION);
animRotate.setRepeatCount(5);
And then when it is time for animation to be fired run it
animRotate.start();
Also, consider reading about what PivotX and PivotY are, it may be useful.
Also, using default interpolator will give strange result for rotating 5 times - i think using simple linear interpolator is much better choice.
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);
As we know , the android coordinate system is start from the top left corner of the android screen. The x-axis is down growth and the y-axis is right growth.But I found it's not right for the animation.
For example, I initialized the TranslateAnimation using the constructed function:
TranslateAnimation ta = new TranslateAnimation(0.0f, 200, 0.0f, 200);
Does the coordinate system have changed ? I found it didn't start from the top left corner.
Then I initialized the other translateAnimation for moving up and right direction :
TranslateAnimation ta = new TranslateAnimation(0.0f, 200, 0.0f, -200);
ta.setReaptMode(Animation.REVERSE);
The same behavior would be found.
I am confused about it.
I believe that constructor for TranslateAnimation uses deltas. See this. Or look at the constructor sig. : (float fromXDelta, float toXDelta, float fromYDelta, float toYDelta). So if you want your anim. to jump up first, you could use a negative third ctor param.
More precisely:
An animation can never start until after the layout has been measured. One usually shouldn't have to worry about how this works beyond that the algorithm is mostly very good and you can take control of its strategies by setting layout parameters. In short, by the time an animation might be started, we know where you want the view to be on the screen, because you set layout parameters.
Translate animation then takes deltas from that position. So your current animation shouldn't start from the top left, but rather wherever those layout params were evaluated by onMeasure.
Some would say- how annoying. It's gonna get complicated even if you just want to do some simple up-down type animations... Well, here's an advisable development strategy; it snould make android animation development a breeeze. Set an animationListener on every animation. In onAnimationEnd, in possibly a parametized way, reset the layout parameters on the view your animating to where you expect it to be. That way, you'll get no surprising "jumps" when you re-apply an animation again. You may need to invalidate in some circumstances, or clearAnimation. The reason that this works is that the measure pass will be caused to come round again and you'll have a new offset for your TranslateAnimation. Finally, you may want to do all this resetting posted to the message queue of a view using post(Runnable runnable) in the listener, so you're off the last pass of the animation draw.
I too found android Animations can occasionally surprise you and cause jumpy behaviour. But if you do it like this, constructors taking delta params shouldn't be confusing again.
So if I have a translation animation like
Animation anim = new TranslateAnimation(0, 0, 0, OFFSET);
anim.setDuration(1000L);
anim.setAnimationListener(listener);
anim.setFillAfter(true);
and I apply this to a textswitcher so that given a offset, the textswitcher will move from a location, A, up or down.
My textswitcher will stay at a given location, B, after the animation due to the setfillafter. How can I then from that location, B, reverse the animation and go back to location, A?
The Overall Question
So I'm translating a textswitcher down and then up, but of course, setfillafter only translates the bitmap of the view and not the view itself, so this may not be the best approach. I've also tried to do an animation and then offset of the view, but that looks glitchy. So basically, I want a view(textswitcher) which a swipe/fling down will move it down and touching(onClick) it when it's down will move it back up (same animation reversed). How can I do this?
I know how to do the swipe/fling and onClick stuff, just not how to implement the correct animation.
Perhaps you may want to consider adding an on touch listener to see where you touched it last, If above move up with a constant animation. This is if im understanding the question correctly.