View.startAnimation Delays Execution for Empty Container Views

androidUnable to sleep, I got hacking at our upcoming release of Wheel of Yum this morning only to get totally stuck on a bug in how Android animates empty container views. In our particular case we have a custom view derived from FrameLayout that adds a single LinearLayout as it’s only child view upon construction. At runtime, our custom view listens for Touch events and dynamically addsremoves various ImageView instances to the inner LinearLayout. When a given Touch event is complete (i.e. MotionEvent.ACTION_UP) the LinearLayout starts a fade-out style animation:

linearLayout.startAnimation(fadeOutAnimation);

In our case fadeOutAnimation is also wired to an AnimationListener where we do some clean up when onAnimationEnd() is called.

Pretty straight forward. Given the typical use case this works just as expected. However, I noticed that occasionally our clean up code was being called when I wasn’t expecting, which in turn was causing a NULL pointer exception. I racked my brain on this far longer than a human should, but the connection became clear to me: the only time I was seeing our clean up code called unexpectedly was when our control’s LinearLayout had no child views and the fadeOutAnimation was issued.

Instead of raising an exception or just short-circuiting tho, Android was waiting until the LinearLayout was next given a child view to execute the animation! Here’s a workflow to clarify:

Typical Execution
1. User touches down our custom view
2. User moves finger around causing ImageViews to be inserted into our custom view’s LinearLayout
3. User releases (touches up) from our custom view
4. Fadeout animation is played
5. Clean up

Unexpected Execution
1. User touches down our custom view
2. User moves finger around causing ImageViews to be inserted into our custom view’s LinearLayout
3. User moves finger around such that all ImageViews are removed, leaving LinearLayout empty
3. User releases (touches up) from our custom view
4. Fadeout animation is issued, but Android doesn’t execute
5. User touches down again
6. User moves finger causing at least one ImageView to be inserted into our custom view’s LinearLayout
7. Android now decides to execute fade out animation issued in step 4
8. Human sacrifice, dogs and cats living together… mass hysteria!

Nasty bug for sure. Fortunately, the workaround was simple enough in our case:


if(linearLayout.getChildCount() > 0)
    linearLayout.startAnimation(fadeOutAnimation);

2 thoughts on “View.startAnimation Delays Execution for Empty Container Views

  1. hey,Superb blogging dude! i am Fed up with using RSS feeds and do you use twitter?so i can follow you there:D.
    PS:Have you thought about putting video to this web site to keep the people more interested?I think it works.Best regards, Franchesca Fabio

Comments are closed.