Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making Android AnimatorSet stop animating

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.

like image 566
wkhatch Avatar asked Aug 11 '14 23:08

wkhatch


People also ask

How do I stop Valueanimator?

Use cancel() or stop() , along with a boolean field somewhere. The boolean serves as a flag to tell onAnimationEnd() whether or not it should do its regular work. Default that boolean to true ; flip it to false when you want to block normal animation-end processing.


2 Answers

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();
like image 131
Aniket Thakur Avatar answered Oct 28 '22 01:10

Aniket Thakur


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.

like image 35
mjp66 Avatar answered Oct 28 '22 02:10

mjp66