Making Android AnimatorSet stop animating
Asked Answered
A

2

6

I have the following AnimatorSet method:

private AnimatorSet dialCenterThrob() {
    int bpm = workoutStream.getHeartRate();
    dialCenterImageView.clearAnimation();
    AnimatorSet finalSet = new AnimatorSet();

    ObjectAnimator pulseX = ObjectAnimator.ofFloat(dialCenterImageView, View.SCALE_X, 0.98f, 1.06f);
    ObjectAnimator pulseY = ObjectAnimator.ofFloat(dialCenterImageView, View.SCALE_Y, 0.98f, 1.06f);

    pulseX.setRepeatMode(ObjectAnimator.REVERSE);
    pulseX.setRepeatCount(ObjectAnimator.INFINITE);
    pulseY.setRepeatMode(ObjectAnimator.REVERSE);
    pulseY.setRepeatCount(ObjectAnimator.INFINITE);
    pulseX.setDuration(bpm);
    pulseY.setDuration(bpm);
    pulseX.setInterpolator(new AccelerateInterpolator());
    pulseY.setInterpolator(new AccelerateInterpolator());

    finalSet.playTogether(pulseX, pulseY);

    return finalSet;
}

This is set on a var, called throbber, and is occasionally updated by this method:

private void updateThrobbing() {
    if (hasThrob()) {
        throbber = dialCenterThrob();
        throbber.start();
    } else {
        if (throbber != null && throbber.isRunning()) {
            stopThrobbing();
        }
    }
}

But I cannot get it to stop animating, and here's the method that currently attempts to do so:

public void stopThrobbing() {
    List<Animator> throbbers = throbber.getChildAnimations();
    for(Animator animator : throbbers) {
        //accomplishes nothing
        ((ObjectAnimator)animator).setRepeatCount(0);
        ((ObjectAnimator)animator).setRepeatMode(0);
    }

    throbber.pause(); //nothing
    throbber.cancel(); //and again, nothing
    throbber.end();//shocking, I know, but really, nothing
    throbber = null;//you'd think this would definitely do it, but no
    //desparate attempt, in vein, of course
    dialCenterImageView.clearAnimation();
}

I cannot get it to stop animating. Update: I just tried storing local ref's to the individual object animators, and then calling setRepeatCount, mode, pause, end, cancel on each one, and still nothing.

Aurelie answered 11/8, 2014 at 23:33 Comment(6)
Please make sure you format/indent your code next time. You will get more answers if you do... it was very difficult to read before I tidied it up.Epicurean
Also, calling clearAnimation will have absolutely no effect here. That method clears a view Animation, which is a totally different concept than object Animators.Epicurean
Also, there is a typo in your code: pulseX.setRepeatMode(ObjectAnimator.);. Could you fix this?Epicurean
Thanks Alex. Do you have an actual answer?Aurelie
I've resolved this by not using infinite repeatCount, and instead, doing some calculations to determine the repeat count. Still, it's BS that it won't cancel/stop no matter what.Aurelie
any object animator, or animatorset with repeatCount set to Infinite will NOT stop, no matter what you do, short of leaving the view.Aurelie
J
30

dialCenterImageView.clearAnimation();

This will have no affect on animations created by ObjectAnimator. You can only clear animation which you have started on the view by startAnimation()

findViewById(R.id.yourViewId).startAnimation(yourAnimation);
findViewById(R.id.yourViewId).clearAnimation();

any object animator, or animatorset with repeatCount set to Infinite will NOT stop, no matter what you do, short of leaving the view.

True that! Learned this today the hard way. So will add my two cents. You need to store the reference of the ObjectAnimator instance and later call cancel() on it.

I encountered this when animation was still continuing after rotating your android phone screen in which case your activity is essentially re created with new layout.

So this is what I did

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    ObjectAnimator buttonOneObjectAnimator = myOnClickListener.getButtonOneColorAnim();
    if(buttonOneObjectAnimator != null)
        buttonOneObjectAnimator.cancel();
}

You can very well do it in onPause() as well.

Another important point to note. If you call start() on your ObjectAnimator instance n times then you will have to call cancel() n times for animation to completely stop.

Also if you have AnimatorSet listeners added , then make sure you have removed the listeners before calling cancel.

yourAnimatorSet.removeAllListeners();
yourAnimatorSet.end();
yourAnimatorSet.cancel();
Jiggle answered 13/5, 2015 at 19:19 Comment(1)
Excellent stuff here, Aniket; thanks. It seems that maybe my calls to cancel weren't working because I wasn't removing the listeners first. If I get some time, I'll revert back to this point in time, just out of curiosity to see if that works. Thanks again!Aurelie
F
4

Late response here but, what I did, no thanks to google's habit of leaving things half-baked, was to pass the view's ObjectAnimator instance in its tag, which needs to be known in order to be able to stop it.

Example start/cancel infinite rotation on a view...

private void rotateStart(View view) {
    ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotation", 0f, 360f);
    // set animator instance as view's tag
    view.setTag(animator); 
    animator.setDuration(800);
    animator.setRepeatMode(ObjectAnimator.RESTART);
    animator.setRepeatCount(ObjectAnimator.INFINITE);
    animator.start();
}

private void rotateCancel(View view) {
    // get view's tag, which is its animator instance
    ObjectAnimator animator = (ObjectAnimator) view.getTag();
    if (animator != null) {
        animator.cancel();
    }
}

I'd assume this would do the job whether it's a single animation or a set.

Florez answered 3/3, 2018 at 18:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.