11

I'm doing an animation of bubbles on the screen, but the bubbles stop after finishing the animation time. How do I repeat the animation or make it infinite?

bub.animate();
bub.animate().x(x2).y(y2);
bub.animate().setDuration(animationTime);       
bub.animate().setListener(new AnimatorListenerAdapter() {

    @Override
    public void onAnimationStart(Animator animation) {
        animators.add(animation); 
    } 

    @Override
    public void onAnimationRepeat(Animator animation) {
    }

    @Override
    public void onAnimationEnd(Animator animation) {
    }
});
user3901032
  • 121
  • 1
  • 1
  • 5
  • possible duplicate of [How to generate looping animation with ViewPropertyAnimator?](http://stackoverflow.com/questions/15815784/how-to-generate-looping-animation-with-viewpropertyanimator) – kaka Aug 17 '14 at 00:12
  • You can also use `ValueAnimator` which supports repeats, https://developer.android.com/reference/android/animation/ValueAnimator.html –  Apr 09 '18 at 11:39

6 Answers6

15

Since ViewPropertyAnimator is only good for simple animations, use more advanced ObjectAnimator class - basically method setRepeatCount and additionally setRepeatMode.

asylume
  • 534
  • 3
  • 6
  • 1
    Yes, `ViewPropertyAnimator` is used for simple animations, for more complex usage, try `ObjectAnimator`. Sorry for unclear answer. – asylume Aug 17 '14 at 00:52
  • @asylume according to the dozen topics in here there is still no *good* way to repeat an `AnimatorSet` that consists of two `ObjectAnimator`s. If I missed smth, hit me up, please – ivan8m8 Feb 26 '19 at 18:21
9

You can use CycleInterpolator. For example, like this:

    int durationMs = 60000;
    int cycleDurationMs = 1000;
    view.setAlpha(0f);
    view.animate().alpha(1f)
            .setInterpolator(new CycleInterpolator(durationMs / cycleDurationMs))
            .setDuration(durationMs)
            .start();
Dmide
  • 6,422
  • 3
  • 24
  • 31
8

Here is an example in Kotlin with a simple way to repeat the animation by recursively calling it in withEndAction

Example

private var animationCount = 0

private fun gyrate() {
    val scale = if (animationCount++ % 2 == 0) 0.92f else 1f
    animate().scaleX(scale).scaleY(scale).setDuration(725).withEndAction(::gyrate)
}

This repeatedly animates the size of a view to get smaller, return to normal, get smaller, return to normal, etc. This is a pretty simple pattern to repeat whatever animation you'd like.

Trevor
  • 1,349
  • 10
  • 16
  • There is a problem with this solution. When you minimize the app this code will still work. So, animation needed to be paused (canceled) when the app is minimized and started again when app is open again – Aleksandr Urzhumtcev Dec 28 '21 at 07:53
7

This is actually possible. Here's an example of rotating a view:

        final ViewPropertyAnimator animator = view.animate().rotation(360).setInterpolator(new LinearInterpolator()).setDuration(1000);

        animator.setListener(new android.animation.Animator.AnimatorListener() {
            ...

            @Override
            public void onAnimationEnd(final android.animation.Animator animation) {
                animation.setListener(null);
                view.setRotation(0);
                view.animate().rotation(360).setInterpolator(new LinearInterpolator()).setDuration(1000).setListener(this).start();
            }

        });

You can also use "withEndAction" instead of a listener.

android developer
  • 114,585
  • 152
  • 739
  • 1,270
0
final ViewPropertyAnimator animator = view.animate().rotation(360).setInterpolator(new LinearInterpolator()).setDuration(1000); //Animator object

    animator.setListener(new android.animation.Animator.AnimatorListener() {
        ...

        @Override
        public void onAnimationEnd(final android.animation.Animator animation) {
            animation.setListener(this); //It listens for animation's ending and we are passing this to start onAniationEnd method when animation ends, So it works in loop
            view.setRotation(0);
            view.animate().rotation(360).setInterpolator(new LinearInterpolator()).setDuration(1000).setListener(this).start();
        }

    });
  • While this code may answer the question, providing information on how and why it solves the problem improves its long-term value – L_J Jun 30 '18 at 17:16
0

in kotlin you can do it like this. create a runnable. inside it animate the view and set withEndAction to runnable itself. and at the end run runnable to animation start.

var runnable: Runnable? = null
runnable = Runnable {
    view.animate()
        .setDuration(10000)
        .rotationBy(360F)
        .setInterpolator(LinearInterpolator())
        .withEndAction(runnable)
        .start()
}
runnable.run()
codegames
  • 1,651
  • 18
  • 16