Mitulát báti
Mitulát báti

Reputation: 2166

How to stop every animation on an ImageView

I'm creating a ringing bell animation (an imageview rotated by 10 degrees and then -10). I'm setting two RotateAnimations and AnimationListeners, in both's onAnimationEnd I start the other animation on the ImageView. Here's how:

onCreate:

final RotateAnimation rotateAnimationLeft = new RotateAnimation(-10, 10, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
final RotateAnimation rotateAnimationRight = new RotateAnimation(10, -10, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

rotateAnimationLeft.setDuration(150);
rotateAnimationRight.setDuration(150);

rotateAnimationLeft.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {
    }

    @Override
    public void onAnimationEnd(Animation animation) {
        ivBell.startAnimation(rotateAnimationRight);
    }

    @Override
    public void onAnimationRepeat(Animation animation) {
    }
});

rotateAnimationRight.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {
    }

    @Override
    public void onAnimationEnd(Animation animation) {
        ivBell.startAnimation(rotateAnimationLeft);
    }

    @Override
    public void onAnimationRepeat(Animation animation) {
    }
});

ivBell.startAnimation(rotateAnimationRight);

I set up an onTouchListener in which I want to stop the animation.

ivBell.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        final int X = (int) event.getRawX();

        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                ivBell.clearAnimation();
                break;
        }
    }
}

It doesn't work. What does it need to stop?

(or if this is a wrong approach, I'd appreciate some recommendations how I should ring that bell :) Thanks!)

Upvotes: 0

Views: 34

Answers (1)

Chrisvin Jem
Chrisvin Jem

Reputation: 4070

The issue here is that whilst you're clearing the animation that's currently running, the animation end triggers the next animation (starting a new cycle). You need to remove the animation listener (set it to null) and then clear the animation,

if(ivBell.getAnimation() != null) {
    ivBell.getAnimation().setAnimationListener(null);
    ivBell.clearAnimation();
}

But in this case, you'd need to store the listener in a separate variable (incase you want to use it again). Maybe a much simpler alternative would be to just use a boolean flag that can be used to determine whether the 'subsequent' animations should be started in the animation listeners.

public class Main2Activity extends AppCompatActivity {

    boolean shouldAnimateFlag = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        final ImageView ivBell = findViewById(R.id.ivBell);

        final RotateAnimation rotateAnimationLeft = new RotateAnimation(-10, 10, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        final RotateAnimation rotateAnimationRight = new RotateAnimation(10, -10, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

        rotateAnimationLeft.setDuration(150);
        rotateAnimationRight.setDuration(150);

        rotateAnimationLeft.setAnimationListener(new Animation.AnimationListener() {
            @Override public void onAnimationStart(Animation animation) { }

            @Override
            public void onAnimationEnd(Animation animation) {
                if(shouldAnimateFlag) {
                    ivBell.startAnimation(rotateAnimationRight);
                }
            }

            @Override public void onAnimationRepeat(Animation animation) { }
        });

        rotateAnimationRight.setAnimationListener(new Animation.AnimationListener() {
            @Override public void onAnimationStart(Animation animation) { }

            @Override
            public void onAnimationEnd(Animation animation) {
                if (shouldAnimateFlag) {
                    ivBell.startAnimation(rotateAnimationLeft);
                }
            }

            @Override public void onAnimationRepeat(Animation animation) { }
        });

        ivBell.startAnimation(rotateAnimationRight);

        ivBell.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //The following line will just stop the animation
//                shouldAnimateFlag = false;
                //You can start/stop using the following lines
                if(shouldAnimateFlag) {
                    shouldAnimateFlag = false;
                } else {
                    shouldAnimateFlag = true;
                    ivBell.startAnimation(rotateAnimationRight);
                }
            }
        });
    }
}

Upvotes: 1

Related Questions