How to repeat an AnimationSet with sequentially added animations

14.3k views Asked by At

I am trying to make an animation in my Activity, to be repeated infinite times. I have already tried it in XML file with repeatCount and repeatMode attributes, but it doesn't work. The thing is that myanimation.xml file is constructed of a set of different animations.

My XML file for that animation

<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:interpolator="@android:anim/bounce_interpolator"
>



<translate


    android:startOffset="1000"
    android:fillAfter="true"
    android:fromXDelta="10"
    android:fromYDelta="10"
    android:toXDelta="50"
    android:toYDelta="-200"
    android:duration="1800"
    android:interpolator="@android:anim/bounce_interpolator"

    />



<translate

    android:fillAfter="true"
    android:startOffset="2000"
    android:fromYDelta="10"
    android:fromXDelta="10"
    android:toXDelta="100"
    android:toYDelta="270"
    android:duration="1800"
    android:interpolator="@android:anim/bounce_interpolator" />

<translate

    android:fillAfter="true"
    android:startOffset="3000"
    android:fromYDelta="10"
    android:fromXDelta="10"
    android:toXDelta="130"
    android:toYDelta="-270"
    android:duration="1800"
    android:interpolator="@android:anim/bounce_interpolator"
    />

<translate

    android:fillAfter="true"
    android:startOffset="4000"
    android:fromYDelta="10"
    android:fromXDelta="10"
    android:toXDelta="140"
    android:toYDelta="270"
    android:duration="1800"
    android:interpolator="@android:anim/bounce_interpolator"
    />

<translate

    android:fillAfter="true"
    android:startOffset="5000"
    android:fromYDelta="10"
    android:fromXDelta="10"
    android:toXDelta="90"
    android:toYDelta="-270"
    android:duration="1800"
    android:interpolator="@android:anim/bounce_interpolator"
    />

And in onCreate() I have animation tied to a ImageView object.

    ImageView ball = (ImageView) findViewById(R.id.animationBall);
    final Animation myAnimation = AnimationUtils.loadAnimation(this,   R.anim.ball_animation);
    ball.startAnimation(myAnimation);

The animation works fine, the only thing is that it doesn't want to repeat itself, even if I set the setRepeatMode() or setRepeatCount() methods.

2

There are 2 answers

5
Yash Sampat On BEST ANSWER

For what its worth, setRepeatMode() and setRepeatCount() have to be set on the Animation objects, and not on the AnimationSet object. That's potentially a mistake you may have made.

So either call those methods on the Animation objects or add those attributes to the XML of the translate schema.

Another approach is to set an endlessly repeating animation as follows:

mAnimationSet.addListener(new AnimatorListenerAdapter() {

    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        mAnimationSet.start();
    }

});
mAnimationSet.start();
0
j2emanue On

Y.S answer seems ok but the animation kept going even though i wanted it cancelled at some point. so i did this:

 animations.playSequentially(
                objectAnimator1,objectAnimator2)



animations.addListener(object: Animator.AnimatorListener{
       var isCancelled = false
        override fun onAnimationRepeat(animation: Animator?) {
        }

        override fun onAnimationCancel(animation: Animator?) {
            isCancelled = true
        }

        override fun onAnimationStart(animation: Animator?) {
        }

        override fun onAnimationEnd(animation: Animator?) {
           if(isCancelled.not()) animations.start()
        }

    })
    animations.start()

UPDATE: FOUND OUT ktx has a few extension functions: we can remove the boilerplate overloads and use this:

inline fun Animator.addListener(
    crossinline onEnd: (animator: Animator) -> Unit = {},
    crossinline onStart: (animator: Animator) -> Unit = {},
    crossinline onCancel: (animator: Animator) -> Unit = {},
    crossinline onRepeat: (animator: Animator) -> Unit = {})

so that means you can just do something like this if you just wanted the onEnd called:

 animations.addListener(onEnd = {animations.start() //loop forever })

and instead of cancel just use animations.pause and animations.resume.