9

I have a question concerning ObjectAnimator in Android. I am trying to model a Bounce effect whereby the View slides up (decreasing Y value) and back down after by the same amount 'n', followed by the View sliding up and down again but this time by 'n/2' (so half the distance).

So a bigger bounce, followed by a shallower bounce - i.e., the kinda thing a Mac icon does in the tray when it wants your attention.

Here is what I've tried so far (assume v is a View):

float y = v.getTranslationY(),distance = 20F;

                AnimatorSet s = new AnimatorSet();
                s.play(ObjectAnimator.ofFloat(v, "translationY", y- distance).setDuration(500))
                .before(ObjectAnimator.ofFloat(v, "translationY", y).setDuration(500))
                .before(ObjectAnimator.ofFloat(v, "translationY", y- (distance/2)).setDuration(500))
                .before(ObjectAnimator.ofFloat(v, "translationY", y).setDuration(500));
                s.start();

Ignore the code quality, it's a POC! I was hoping this would work, but it seems to only 'bounce' once as if its combined the animations despite the use of .before().

Could you please show me how I can create complex AnimatorSet chains that do not amalgamate in to one, as I seem to be missing something?

BONUS: For extra points, how can I set the repeat of an AnimatorSet?

Many thanks!

Darius
  • 5,180
  • 5
  • 47
  • 62

3 Answers3

29

OK so I eventually found a fairly neat way to achieve sequential animation by ignoring the fluent builder, and just using the playSequentially() method such that:

AnimatorSet as = new AnimatorSet();
as.playSequentially(ObjectAnimator.ofFloat(...), // anim 1
                    ObjectAnimator.ofFloat(...), // anim 2
                    ObjectAnimator.ofFloat(...), // anim 3
                    ObjectAnimator.ofFloat(...)); // anim 4
as.setDuration(600);
as.start();

Still haven't worked out repeating though, other than a dirty hack involving the callback onAnimationEnd in a listener. Must be a simpler way, so perhaps someone can edit this when they know of one.

Anyway, hope the above helps someone.

Darius
  • 5,180
  • 5
  • 47
  • 62
  • use http://www.jefflinwood.com/2013/04/repeating-android-animations-with-animatorset/ if you want to repeat – Martin Konecny Mar 28 '14 at 15:25
  • "dirty hack involving the callback onAnimationEnd in a listener" - It seems that article describes the same approach – Darius Mar 31 '14 at 11:26
  • Oh I misread your comment. However, a callback for the precise moment a animation ends wouldn't count as a dirty hack IMO. – Martin Konecny Mar 31 '14 at 17:53
  • 2
    @MartinKonecny This question is still getting views so I wanted to say that I no longer think it a dirty hack! Either I'm jaded from the last 6 years or maybe I've just gotten more experience.. or maybe both! – Darius Aug 16 '18 at 08:26
3

When you use the Builder, all returning dependencies refer to the first Animator, so you had 3 bounces happening simultaneously after the first movement. Unfortunately it seems AnimatorSet is broken on some aspects, one of them being repeats : https://code.google.com/p/android/issues/detail?id=17662

Rafael Nobre
  • 5,062
  • 40
  • 40
0

If you are using Kotlin do it like this:

           val animationSet =  AnimatorSet();
            animationSet.playSequentially(cornerAnimation, colorChangeAnimator,cardElevationAnimator )
            animationSet.duration = ANIMATION_INTERVAL_MS;
            animationSet.start();
            animationSet.addListener(object :AnimatorUpdateListener, Animator.AnimatorListener {
                override fun onAnimationEnd(animation: Animator?) {
                    currentColor = toColor
                }
                override fun onAnimationUpdate(animation: ValueAnimator?) {}
                override fun onAnimationRepeat(animation: Animator?) {}
                override fun onAnimationCancel(animation: Animator?) {}
                override fun onAnimationStart(animation: Animator?) {}
            })
Hitesh Sahu
  • 41,955
  • 17
  • 205
  • 154