When reading though the documentation for View Animations you might stumble across the three flags
fillEnabled. You can set the flags in the XML resource of an animation, something like this.
<scale android:duration="300" android:fillAfter="true" android:fillBefore="false" android:fillEnabled="true" android:fromXScale="0.0" android:fromYScale="0.0" android:toXScale="1.0" android:toYScale="1.0" />
Or you can programmatically set the flags like this
ScaleAnimation scale = new ScaleANimation(0.0f, 1.0f, 0.0f, 1.0f); scale.setFillAfter(true); scale.setFillBefore(false); scale.setFillEnabled(true);
At first, the documentation seems reasonable.
fillAfter determines whether the final transformation is applied after the animation has finished and
fillBefore determines whether the initial transformation is applied before the animation starts. However, the value of
fillBefore only has any influence if
fillEnabled is set to
false the transformation will be applied before the start of the animation, no matter what the value of
This means that, in order to prevent the system from applying the transformation before the start of the animation you have to set
false. In any other case the transformation will be applied.
According to the documentation, the
fillEnabled flag only influences the behaviour of the
fillBefore flag. You may wonder why there are two flags controlling one single behaviour. In essence one flag should be enough. In this brilliant article Chet Haase explains that this is due to the evolution of the behaviour between API levels combined with the requirement that compatibility is preserved. He also refers to an error in the documentation that was supposedly corrected in 2011.
It turns out that the documentation is still wrong!
fillEnabled does, in fact, also influence the behaviour of the
fillAfter flag, but in a more subtle way.
Sequences of Animations in Sets
The real behaviour comes to light when you create sequences of animations. As I showed in my last post, we can combine animations to be played on after another inside an animation set using the
startOffset property. Let’s take a look at the following animation.
<set android:shareInterpolator="true" android:fillBefore="true" android:fillAfter="false"> <translate android:fillEnabled="true" android:duration="300" android:fromXDelta="-100" android:fromYDelta="0" android:toXDelta="100" android:toYDelta="0" /> <translate android:duration="300" android:startOffset="300" android:fromXDelta="0" android:fromYDelta="-100" android:toXDelta="0" android:toYDelta="100" /> </set>
The animation consists of two translate animations, the first moves the view in the x direction and the second moves the view in the y direction. The second animation in the set has an offset of 300 milliseconds, so the two animations are played in sequence. Let’s call the first translation
transX and the second translation
First of all, let’s look again at the behaviour of
fillBefore. As stated above the only way to avoid the transformation to be applied before the animation starts is to set
false. The documentation states that the values of
fillAfter are pushed down from the animation set. On the other hand, it is the value of
fillEnabled of the individual transformation that has an impact on the behaviour. So, to avoid the transformation
transY to be applied before the start of the animation one has to set the following flags.
set.fillBefore = false transY.fillEnabled = true
The undocumented behaviour of fillAfter
The documentation, in its current form, will make you believe that the
fillAfter property of the animation set will influence whether the transformation is applied after the animation has finished. However, we have to distinguish between the end of the complete animation and the end of the individual animation. In the example above the first translation
transX finishes before the end of the complete animation. If
true then all the transformations will be applied after the animations defining them have finished.
If, on the other hand,
false then the transformations will not be applied after the complete animation set has finished. But it is then up to
transX.fillEnabled to specify if the transformation
transX is applied in the time between the end of the first translate animation and the end of the complete set of animations.
This is all a bit confusing. The behaviour of
fillAfter is not symmetric. It took me quite some time to get my head around this issue. So I have created the figure below, where I have tried to illustrate how the flags influence the application of the transformations.
The animation set,
set, contains two animations,
anim1 plays first and then
anim2. The end of
anim2 determines the end of the complete animation. The figure represents the timeline. The yellow boxes indicate the times when the individual animations are playing. Outside of the yellow areas I have specified under which conditions the transformations of
anim2 are applied.
In the time before the start of the animation, the initial transformation of
anim1 will be applied if (and only if)
(set.fillBefore || !anim1.fillEnabled) == true
Similarly, the initial transformation of
anim2 will be applied if
(set.fillBefore || !anim2.fillEnabled) == true
After both animations have finished the final transformations of both
anim2 will be applied if
set.fillAfter == true
However, in the time after
anim1 has finished but
anim2 is still running, the final transformation of
anim1 will be applied if
(set.fillAfter || !anim1.fillEnabled) == true
This means that, under default conditions, the transformation of
anim1 is still applied during this time even if
set.fillAfter==false. But setting
true will prevent the transformation from being applied right after
anim1 has finished if
All of this means that you have slightly more fine grained control over the behaviour after the end of the animations than you have before the start of the animations. Why this asymmetry has been introduced will probably remain a mystery.