I'm creating a game and I would like to display a simple "score"-animation to the player when credits are given to him. This is the view I throw onto the screen:
public class Score extends FrameLayout { public Score(Context context, int score) { super(context); TextView txt = new TextView(context); txt.setText(String.valueOf(score).toUpperCase()); addView(txt); Animation anim = AnimationUtils.loadAnimation(context, R.anim.score); startAnimation(anim); anim.setAnimationListener(animationListener); } private void Remove(){ ViewGroup parent = (ViewGroup)getParent(); parent.removeView(this); } private AnimationListener animationListener = new AnimationListener() { @Override public void onAnimationEnd(Animation animation) { Remove(); } }; }
This code actually works pretty well as long as there is only ONE score animation on screen at any given time. If the player scores again, before the last score was removed, the app crashes - probably because the second score gets the event to remove itself during animation.. Is this a bad practice of using Animation? How would you guys handle this?
Use clearAnimation() to stop an animation.
I also found that when removing a view from its parent after applying an animation to this view (using onAnimationEnd) crashes with NPE on the dispatchDraw of the parent.
The only solution I found is to trigger the removal inside a post call. Normally all UI modification must be done on the UI thread, so I added a runOnUiThread call on the activity, but it could be useless (it works for me without that).
Animation animation = AnimationUtils.loadAnimation(parentView.getContext(), animationId); animation.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation paramAnimation) { } public void onAnimationRepeat(Animation paramAnimation) { } public void onAnimationEnd(Animation paramAnimation) { // without the post method, the main UI crashes if the view is removed parentView.post(new Runnable() { public void run() { // it works without the runOnUiThread, but all UI updates must // be done on the UI thread activity.runOnUiThread(new Runnable() { public void run() { parentView.removeView(view); } }); } }); } }); view.setVisibility(visibility()); view.startAnimation(animation);
For Kotlin language and using View Binding, this my solution:
animation.setAnimationListener(object : Animation.AnimationListener { override fun onAnimationStart(p0: Animation?) { } override fun onAnimationEnd(p0: Animation?) { mViewBinding .parentViewContainer .post { //The code below will be run on UI thread. mViewBinding .parentViewContainer .removeView(view) } } override fun onAnimationRepeat(p0: Animation?) { } })
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With