One visual aspect of an app which can make or break the user experience is the use of animations. They can add that bit of pizazz which really makes an app look polished and refined. Or, they can overburden the user and the device with too much going on and kill the app’s visual appeal. Like other modern UI driven platforms, Android does include animation support. However, Android animations are interesting and have evolved over time. This has brought app developers more power and flexibility, but like any API it can be difficult to navigate. This is especially true with regards to the use of the different techniques and APIs exposed by the framework. The different mechanisms have subtly different names and can use XML configuration which can look very similar. Android animations can be categorized in three basic buckets: tween, drawable sequence and property animation. In this first article in this multi-part series we’ll start our examination of Android animation capabilities by looking at the original ways to animate things: tween and drawable animations.
Note that when I say animations, I’m referring to view or screen type animations, not 3D graphics or OpenGL based animations. Diving into OpenGL is a much bigger topic and is separate from animating all or part of our app’s UI.
Tween Animation
A tween animation is also called a view animation. This type of animation is performed on the content of a View
. A tween animation applies one or more transformations on the content of a view, such as its position, size or rotation. Tween animations are simple to use and understand, so for developers just getting started with Android animations in their apps it is a great option. But, the tween animation is limited in exactly what it can do and it is not necessarily as efficient as property animation, which I’ll explore in the next article in this series.
To begin, let’s cover some basics with regards to tween animations:
- A tween animation is a change to some visual characteristic of the view over a certain period of time.
- The changes made from start to finish are determined by the system using an
Interpolator
- More than one change can be applied to the same view and can be executed serially or simultaneously
- A tween can be specified using XML or programmatically. Just like defining layouts, using XML to define animations is much more flexible and readable.
The simplest way to look at this is via an XML example which will fade a view out in 500ms:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <alpha android:duration="500ms" android:fromAlpha="1.0" android:toAlpha="0.0" /> </set>
To use this in code, you inflate it using the AnimationUtils
class and then apply it to a view using the setAnimation()
or startAnimation()
calls. As an example:
Animation anim = AnimationUtils.loadAnimation(this, R.anim.sample1); myView.startAnimation(anim);
Animations support a callback mechanism which can be used to notify your app when an animation starts, ends and is repeated. Simply set an Animation.AnimationListener
instance to the Animation
before starting it.
The Animation
abstract class represents an animation in code. There are pre-defined classes for scaling, rotating, transforming location and alpha. In the example above, the <alpha>
tag is used to specify an AlphaAnimation
class. These different classes can be combined in interesting ways via the AnimationSet
class. In order to define an animation in XML, the root tag is required to be the <set> tag. This creates an AnimationSet
object on inflation, which is a subclass of Animation
. An AnimationSet
is what is used to apply multiple animations together.
Using the example above, we can change this so the animation is both an alpha fade out and a scale down animation:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <alpha android:duration="500ms" android:fromAlpha="1.0" android:toAlpha="0.0" /> <scale android:duration="500ms" android:fromXScale="1.0" android:toXScale="0.5" android:fromYScale="1.0" android:toYScale="0.5" /> </set>
The one key thing we’re missing at this point is the Interpolator
for our animation. If not specified, the default is the AccelerateDecelerateInterpolator
. What exactly is this thing? The animation subsystem uses an Interpolator
to smooth and alter the animation over its duration. For each step in the animation, the system asks the interpolator to provide an alternative step value to use. The step ranges from 0.0 to 1.0 and is interpreted by each animation in a different way. For example, in our scale animation above the scale is going from 100% to 50% over the duration. The animation is walking through its paces each “step” over the duration, but the interpolator is used to change what is done by transforming this value (rather than just using a linear one.) In the default case, AccelerateDecelerateInterpolator
, the value will start slowly, accelerate through the middle range then slow down before the end. In contrast, the BounceInterpolator
will “bounce” through the animation over the entire duration. This can sometimes be hard to visualize, so the easiest way to look at this is either via working example or by graphing the Interpolator transform value. Below are some screen shots of an app used to show a simple animation and the different interpolators via a simple graph. See the end of this article for a link to the sources for this app.
Drawable Animation
In addition to the tween based animations, Android also supports drawable animations. Rather than alter the view characteristics themselves, this is used to apply a series of drawables or pictures to create the animation effect. This are typically used for animated backgrounds or a View
which need to visually change. Like the tween based animations, you can create these in code using the AnimationDrawable
class. But, it’s far easier and more flexible to do it via XML. For example, the Android framework uses this technique to animation indeterminate progress bars. The animation is called progress_indeterminate_horizontal_holo
. The contents of this XML file and the first two images (from the KitKat tree) are shown below for clarity.
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/progressbar_indeterminate_holo1" android:duration="50" /> <item android:drawable="@drawable/progressbar_indeterminate_holo2" android:duration="50" /> <item android:drawable="@drawable/progressbar_indeterminate_holo3" android:duration="50" /> <item android:drawable="@drawable/progressbar_indeterminate_holo4" android:duration="50" /> <item android:drawable="@drawable/progressbar_indeterminate_holo5" android:duration="50" /> <item android:drawable="@drawable/progressbar_indeterminate_holo6" android:duration="50" /> <item android:drawable="@drawable/progressbar_indeterminate_holo7" android:duration="50" /> <item android:drawable="@drawable/progressbar_indeterminate_holo8" android:duration="50" /> </animation-list>
If we wanted to use this animation for the background of a view and start the animation when a button is clicked, it is just a couple of lines of code:
@Override protected void onCreate(Bundle savedInstanceState) { ... mProgress = findViewById(R.id.sample_progress); mProgress.setBackgroundResource(android.R.drawable.progress_indeterminate_horizaontal_holo); mProgAnim = (AnimationDrawable)mProgress.getBackground(); ... } @Override public void onClick(View v) { ... mProgAnim.start(); }
Limitations
The two basic Android animations covered here are just that: basic. They provide simple, flexible and easy to use animation capabilities. But, they do have some limitations:
- The tween animations only support a subset of the visual parts of the
View
: alpha, scale, location with the parent and rotation. If you wish to animate other aspects of the View object you cannot use this technique. - The rotation animation is limited to rotating only within the X-Y plane. You cannot use this to animation the Z axis (make the view rotate in/out of the screen visually.)
- The drawable animations require you to provide graphics assets for each step of the animation. For simple animations this is a great option.
- But, for drawables you also need to provide different assets for each screen density and know the dimensions of the images to ensure there are no scaling issues.
In the next installment in this series, we’ll look at the Animator mechanism for providing animations. Until then: experiment and enjoy!
References
[1] Animation Show sample app: https://github.com/hiq-larryschiefer/AminShow.git