Skip to main content

The Mysterious Behavior of fillBefore, fillAfter, and fillEnabled

A bug was filed on android.com recently that had me poring through the code and docs to understand three boolean flags in the old Animation class: fillBefore, fillAfter, and fillEnabled. On the surface, these properties don't seem that difficult to understand; they control how animations behave before and after they run. But between some complicated interactions of the properties and some, er, inaccuracies in the reference docs, it turned out to be somewhat tricky to understand how they work and how they're supposed to work. Once I got through that exercise (including fixing the docs - look for those fixes in a future release), I thought it might be helpful to explain how these flags really work.



First, let's cover the behavior of fillBefore and fillAfter. We'll get to fillEnabled and it's, um, special behavior after that.



Before and After



fillBefore and fillAfter are pretty simple, conceptually; they define how an animation behaves before and after it runs. fillBefore controls whether the initial value of the animation is applied before its start time and fillAfter controls whether the animation's ending value persists after it ends. There are a couple of important nuances to understand, however.




  • start time: The starting time of an animation, for the purposes of fillBefore, is not the time when you call startAnimation() on a View. Rather, it's the time that the animation will actually start running. These two times are the same if there is no startOffset set on the animation, but if you want to delay your animation, you might set a startOffset value to achieve that delay. fillBefore controls whether the animation will use the initial value of the animation during that startOffset phase.

  • AnimationSet: If you want to control the fill behavior of an animation that is inside an AnimationSet, it is certainly possible to do this. But if you want to control what happens outside the runtime of that AnimationSet, then you need to set the fill behavior on the set itself. For example, the fillAfter flag controls whether a ScaleAnimation's end value is used after it ends. But if the animation you set on your View is actually an AnimationSet containing that inner ScaleAnimation, then you need to set fillAfter on the AnimationSet if you want the value to persist after the AnimationSet ends. You can think of the fill behavior flags as having scope, which is either global (when not contained in an AnimationSet) or local to the AnimationSet in which their contained. Or you can just play with them enough to get the hang of it, like I did. It's also worth noting, as stated in the docs (correctly this time) that if you set the value of fillBefore or fillAfter these values will override those in the child animations of the set.



The default values for these flags are true for fillBefore and false for fillAfter. So by default, animations will set their initial value immediately when the animation starts (regardless of startOffset), but will not persist those values after they end.



So that's all there is to those flags: you set or unset them according to whether you want the animation values to be used outside of when the animation is actually running. Well, sort of...



The Enabler



Here's where the other flag, fillEnabled, comes in. This flag controls when the other flags are actually taken into account. Or that's what some of the docs would have you believe. In actual fact, this flag controls only the behavior of fillBefore, and essentially leaves fillAfter to its own devices.



Here's how the value of fillEnabled works:




  • false: If fillEnabledis false (which it is by default), then the value of fillBefore will be ignored. That's right, you can set or unset it all you want, but it will ignore your wishes and will essentially assume that fillBefore is true.

  • true: When fillEnabled is true, the value of fillBefore will be taken into account to determine whether to apply the animation before it begins. The value of fillAfter, as I said earlier, will be used as-is, regardless of the value of fillEnabled.



All of this means that the only way to get an animation to not persist its starting value before it actually starts running is to set both fillEnabled to true and fillBefore to false. Any other combination will result in the animation being applied before its starting time. Meanwhile, the value of fillAfter is applied directly, regardless of the value of fillEnabled. I believe it is this asymmetric behavior (coupled with an unfortunately generically named "fillEnabled" property and some, well, bugs in the docs) that made these three variables particularly difficult for some people to understand. Some people like me.



At this point, you might be asking yourself why these variables were created and defined in this way. All I can say is, welcome to the wonderful world of API development, where behavior needs to evolve while compatibility is preserved. In any case, I hope this explanation helps those who needed it.



p.s. For those starting to use the new animation system introduced in Android 3.0, you can forget about all of this; there is no fill behavior (before, after, or enabled) for Animator-based animations.

Comments

Popular posts from this blog

Benefits Of Healthy eating Turmeric every day for the body

One teaspoon of turmeric a day to prevent inflammation, accumulation of toxins, pain, and the outbreak of cancer.  Yes, turmeric has been known since 2.5 centuries ago in India, as a plant anti-inflammatory / inflammatory, anti-bacterial, and also have a good detox properties, now proven to prevent Alzheimer's disease and cancer. Turmeric prevents inflammation:  For people who

Women and children overboard

It's the  Catch-22  of clinical trials: to protect pregnant women and children from the risks of untested drugs....we don't test drugs adequately for them. In the last few decades , we've been more concerned about the harms of research than of inadequately tested treatments for everyone, in fact. But for "vulnerable populations,"  like pregnant women and children, the default was to exclude them. And just in case any women might be, or might become, pregnant, it was often easier just to exclude us all from trials. It got so bad, that by the late 1990s, the FDA realized regulations and more for pregnant women - and women generally - had to change. The NIH (National Institutes of Health) took action too. And so few drugs had enough safety and efficacy information for children that, even in official circles, children were being called "therapeutic orphans."  Action began on that, too. There is still a long way to go. But this month there was a sign that

Not a word was spoken (but many were learned)

Video is often used in the EFL classroom for listening comprehension activities, facilitating discussions and, of course, language work. But how can you exploit silent films without any language in them? Since developing learners' linguistic resources should be our primary goal (well, at least the blogger behind the blog thinks so), here are four suggestions on how language (grammar and vocabulary) can be generated from silent clips. Split-viewing Split-viewing is an information gap activity where the class is split into groups with one group facing the screen and the other with their back to the screen. The ones facing the screen than report on what they have seen - this can be done WHILE as well as AFTER they watch. Alternatively, students who are not watching (the ones sitting with their backs to the screen) can be send out of the classroom and come up with a list of the questions to ask the 'watching group'. This works particularly well with action or crime scenes with