sockeqwe
sockeqwe

Reputation: 15919

Repeat AnimatorSet

Is there a simple way to repeat a Android AnimatorSet (infinite)? Can I set a AnimationListener and restart the AnimatorSet by calling start() again?

My AnimatorSet contains two animations that are played sequentially. So if I set the repeat mode of both single animation to repeat, than the first will be repeated while the second runs, right?

Upvotes: 21

Views: 28257

Answers (8)

Hayk Mkrtchyan
Hayk Mkrtchyan

Reputation: 3245

Yet I've couldn't find a working solution with multiple animations, but one solution that works for me is to start again the animation after the ending.

P.S. I didn't handle the cancellation part here.

animatorSet.doOnEnd {
   it.start()
}

Upvotes: 1

Shahab Rauf
Shahab Rauf

Reputation: 3931

Set Infinite repeat count and restart / reverse repeat mode to all child animations

animatorSet.childAnimations.forEach {
            val animator  = it as ObjectAnimator
            animator.repeatCount = ObjectAnimator.INFINITE
            animator.repeatMode = ObjectAnimator.RESTART / REVERSE
}

Upvotes: 3

M Moersalin
M Moersalin

Reputation: 290

No, you can't repeat AnimatorSet, you can only repeat of a single ObjectAnimator/ ValueAnimator

But you can use PropertyValuesHolder, so that you can make an ObjectAnimator from a set of PropertyValuesHolder

here's example

val translateY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, -100f, 100f)
val alpha = PropertyValuesHolder.ofFloat(View.ALPHA, 0.3f, 0.7f)
val scaleX = PropertyValuesHolder.ofFloat(View.SCALE_X, 0.8f, 1.2f)
val scaleY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 0.8f, 1.2f)
// and more

ObjectAnimator.ofPropertyValuesHolder(myView, translateY, alpha, scaleX, scaleY).apply {
    interpolator = AccelerateDecelerateInterpolator()
    // duration of each animation
    duration = 500L
    // repeat infinite count (you can put n times)
    repeatCount = ValueAnimator.INFINITE
    // reverse animation after finish
    repeatMode = ValueAnimator.REVERSE
    // start animation
    start()
}

Upvotes: 3

gaurav414u
gaurav414u

Reputation: 821

So, none of the above options are appropriate.

If you use:

  @Override
  public void onAnimationEnd(Animator animation) {
    if (!mCanceled) {
      animation.start();
    }
  }

you will end up getting stackOverFlow exception sometimes.

The best thing is to do something like:

Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true && getActivity() != null) {
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            set3.start();
                        }
                    });
                    SystemClock.sleep(1200);
                }
            }
        });
        t.start();

Upvotes: -2

wkhatch
wkhatch

Reputation: 2741

set it's child object animators' repeat mode and count;

objectAnimator.setRepeatCount(ObjectAnimator.INFINITE);
objectAnimator.setRepeatMode(ObjectAnimator.RESTART/REVERSE...);

This won't be able to be stopped, or cancelled, however, due to yet another bug.

clearly, I'm not a fan of the myriad ways in which you can animate things in Android, and have them all fail you in one way or the other. Hope this helps somebody else.

Upvotes: 40

user3098724
user3098724

Reputation: 1

How about this?

@Override
public void onAnimationEnd(Animator animation) {
    if (!mCanceled) {
        animation.reset();  //<- added.
        animation.start();
    }
}

Upvotes: -4

daus
daus

Reputation: 396

There is an answer for the first two questions

Is there a simple way to repeat a Android AnimatorSet (infinite)? Can I set a AnimationListener and restart the animatorSet by calling start() again?

Yes, there is:

mAnimationSet.addListener(new AnimatorListenerAdapter() {

  private boolean mCanceled;

  @Override
  public void onAnimationStart(Animator animation) {
    mCanceled = false;
  }

  @Override
  public void onAnimationCancel(Animator animation) {
    mCanceled = true;
  }

  @Override
  public void onAnimationEnd(Animator animation) {
    if (!mCanceled) {
      animation.start();
    }
  }

});
mAnimationSet.start();

The answer for the third question, is no. The first animation will be repeated and after all repetitions the succeeding animation will be started.

Upvotes: 24

Marcin Orlowski
Marcin Orlowski

Reputation: 75629

Out of my head - animation framework is source of pain, especially if you want to support 2.x. I usually had problems with sets trying to do anythig more complexKeep track of with AnimationListener kind-of "player". I keep track on which animation I play (like int etc) and then on onAnimationEnd I start another that should be in sequence. That way I can easily "script" my sequence, and do not bother broken framework.

Upvotes: 0

Related Questions