Reverting animation done with AnimatorSet - android

I am creating an animation with AnimatorSet and when it ends I would like to leave the View where it was.
The code is something like this:
mLastAnimation = new AnimatorSet();
mLastAnimation.playTogether(
ObjectAnimator.ofFloat(mImageView, "scaleX", 1.5f, 1f),
ObjectAnimator.ofFloat(mImageView, "translationY", 40f, 0f));
mLastAnimation.setDuration(3000);
mLastAnimation.addListener(this);
mLastAnimation.start();
// The Activity implements the AnimatorListener interface
#Override
public void onAnimationEnd(Animator animator) {
// Undo the animation changes to the view.
}
EDIT:
I am using the new animation API so setFillAfter() will not work here.

If you are using nineoldandroids there is a function called reverse. You can set the duration to be 0 and call reverse to reverse the animation.

You have to set the properties of the View back to its original values.
For example if you translateY 40 pixels forward, you need to translateY 40 pixels backwards. This is because the actual properties of the View have changed during property animation, not just the way it is rendered.
http://developer.android.com/guide/topics/graphics/prop-animation.html#property-vs-view

While using ObjectAnimator you can simply set
android:repeatMode="reverse"

You can use this:
ObjectAnimator scaleX = ObjectAnimator.ofFloat(mImageView, "scaleX", 1.5f, 1f);
// here is the important part!
scaleX.setRepeatMode(ValueAnimator.REVERSE);
scaleX.setRepeatCount(1);
ObjectAnimator transl = ObjectAnimator.ofFloat(mImageView, "translationY", 40f, 0f));
// here is the important part!
transl.setRepeatMode(ValueAnimator.REVERSE);
transl.setRepeatCount(1);
mLastAnimation = new AnimatorSet();
mLastAnimation.playTogether(scaleX, transl);
// the rest is the same...

Related

Multiple ViewPropertyAnimators

Hope I am not duplicating a question here; I couldn't find one about multiple ViewPropertyAnimators. The goal is to have a view animate from y1 to y2 in 8 seconds. Fade in the first second, and then fade out on the last second.
Here is what I have Tried in my Activity's onCreate():
final View animatingView = findViewById(R.id.animateMe);
animatingView.post(new Runnable() {
#Override
public void run() {
//Translation
animatingView.setY(0);
animatingView.animate().translationY(800).setDuration(8000);
//Fading view in
animatingView.setAlpha(0f);
animatingView.animate().alpha(1f).setDuration(1000);
//Waiting 6 seconds and then fading the view back out
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
animatingView.animate().alpha(0f).setDuration(1000);
}
}, 6000);
}
});
However, the result is a translation from 0 to 800, and alpha from 0 to 1 all in one second. and then 6 seconds later the view fades out. It looks every time I call View.animate() it returns the same ViewPropertyAnimator. Is there a way I can have multiple of them? I was thinking about animating the view's alpha, nesting the view in a relative layout, and then animating the relative layouts translation. I would rather not go that route if I don't have to. Does anyone know of a better solution?
You can solve this by using ObjectAnimator instances directly, rather than using the .animate() abstraction.
ObjectAnimator translationY = ObjectAnimator.ofFloat(animatingView, "translationY", 0f, 800f);
translationY.setDuration(8000);
ObjectAnimator alpha1 = ObjectAnimator.ofFloat(animatingView, "alpha", 0f, 1f);
alpha1.setDuration(1000);
ObjectAnimator alpha2 = ObjectAnimator.ofFloat(animatingView, "alpha", 1f, 0f);
alpha2.setDuration(1000);
alpha2.setStartDelay(7000);
AnimatorSet set = new AnimatorSet();
set.playTogether(translationY, alpha1, alpha2);
set.start();

Bounce animation with depth

how i can add bounce animation to view which will go down and come up but it should do this only for one time .
if i set bounce interpolator with y its bouncing for given duration
but i want it for one time only but it should go say 5dp down and up to current view
ObjectAnimator animator = ObjectAnimator.ofFloat(targetView, "translationY", 0, 50, 0);
animator.setInterpolator(new BounceInterpolator());
animator.setDuration(200);
animator.start();
Use OvershootInterpolator.
Doc:
An interpolator where the change flings forward and overshoots the
last value then comes back.
You can adjust the tension of the overshoot using the constructor with tension parameter:
OvershootInterpolator(float tension)
tension: Amount of overshoot. When tension equals 0.0f, there is no
overshoot and the interpolator becomes a simple deceleration
interpolator.
Default value of tension is 2.0f.
Example using ViewPropertyAnimator:
targetView.animate()
.translationY(50)
.setInterpolator(new OvershootInterpolator())
.setDuration(200);
using ObjectAnimator:
ObjectAnimator animator = ObjectAnimator.ofFloat(targetView, "translationY", 0, 50); // pass only start and end values.
animator.setInterpolator(new OvershootInterpolator());
animator.setDuration(200);
animator.start();

How to use setDelay for animation within an AnimatorSet?

I'm trying to implement a set of animations, but the start delay value does not seem to be respected. Example:
ObjectAnimator a1 = ObjectAnimator.ofFloat(view1, View.ALPHA, 1f, 0f);
a1.setDuration(500);
a1.setStartDelay(500);
ObjectAnimator a2 = ObjectAnimator.ofFloat(view2, "translationX", ...);
a2.setDuration(500);
AnimatorSet set = new AnimatorSet();
set.playTogether(a1, a2);
set.start();
I can see the alpha animation starts immediately. If I don't try to play them together, the delay is respected and works fine. Can the delay not be used if part of an AnimatorSet?
If you want to play the animations in sequence, don't use ObjectAnimator.setStartDelay(). It's not designed for that use case.
Use AnimatorSet.playSequentially() instead:
AnimatorSet set = new AnimatorSet();
set.playSequentially(a2, a1);
set.start();

How to add a delay between animations in AnimatorSet playSequentially()?

I'm using AnimatorSet playSequentially method like this:
AnimatorSet set = new AnimatorSet();
ObjectAnimator in = ObjectAnimator.ofFloat(splash, "alpha", 0f, 1f);
in.setDuration(2500);
in.setInterpolator(new AccelerateInterpolator());
ObjectAnimator out = ObjectAnimator.ofFloat(splash, "alpha", 1f, 0f);
out.setDuration(2500);
out.setInterpolator(new AccelerateInterpolator());
set.playSequentially(in,out);
I whould like to add a delay between animation 1 and 2, like this:
set.playSequentially(in,1000,out);
It is possible to add delays between animations using playSequentially method?
Thank you.
Add this line of code:
out.setStartDelay(1000);
You could set a start delay on the 2nd Animator (i.e. out.setStartDelay(1000)) before adding it to the set.
Rather than setting a start delay on the individual animations,
use the AnimatorSet.after(long delay) function.
AnimatorSet s = new AnimatorSet();
s.play(anim1).after(1000).after(anim2);
AnimatorSet.Builder

Android ScaleAnimation and TranslateAnimation, how to avoid ScaleAnimation movement

I have an AnimationSet with inside a ScaleAnimation and a TranslateAnimation like this:
TranslateAnimation:
TranslateAnimation goTopFromRight =
new TranslateAnimation(0, -(right.getLeft()-top.getLeft()),
0,-(right.getTop()-top.getTop()));
ScaleAnimation:
ScaleAnimation = setSizeForTop = new ScaleAnimation(1, 2, 1, 2);
and AnimationSet:
bringToLeftFromTopAnimationSet = new AnimationSet(true);
bringToTopFromRightAnimationSet.addAnimation(goTopFromRight);
bringToTopFromRightAnimationSet.addAnimation(setSizeForTop);
The problem is that when i try to use only the ScaleAnimation, my item goes to the position i want, but whe I am using the ScaleAnimation with the TranslateAnimation in the AnimationSet, my item translates more than i need, as if ScaleAnimation introduces some supplementary movements abd I don't know how to delete them.
Thank you for your help.
The correct solution is to change order of animations. Scale must go first:
bringToTopFromRightAnimationSet.addAnimation(setSizeForTop);
bringToTopFromRightAnimationSet.addAnimation(goTopFromRight);
To avoid the ScaleAnimation movement when using the ScaleAnimation and TranslateAnimation, you have to multiply the TranslateAnimation parametres with those from ScaleAnimation like this:
TranslateAnimation goRightFromTop;
ScaleAnimation sizeNotUp;
goRightFromTop = new TranslateAnimation(0,(-( invisibleCenterImageView.getLeft() - imageViewRight.getLeft() ))*(1/0.6667f), 0, (-( invisibleCenterImageView.getTop() - imageViewRight.getTop()))*(1/0.6667f));
sizeNotUp = new ScaleAnimation(1,0.6667f,1,0.6667f,Animation.RELATIVE_TO_SELF, (float)0.5, Animation.RELATIVE_TO_SELF, (float)0.5);
And then, surprise you deleted the ScaleAnimation movement.
I remember having weird problems with nested animations as well.
Have you tried setting the pivot point manually? See public ScaleAnimation (float fromX, float toX, float fromY, float toY, float pivotX, float pivotY) from http://developer.android.com/reference/android/view/animation/ScaleAnimation.html for it.
It could work.
My solution is to add a container outside your view, and apply the scale animation to your view while applying translate animation to the container.
Then you can make more complex animation even via XML~

Categories

Resources