So you're thinking about incorporating animations in to your Android app. You've seen first-hand how an appropriate use of animation can transform an app into something you love to use, and you'd like to bring that to your project. There's only one problem - you don't know where to start. Maybe you've done some animating before on another platform, or maybe you've never even thought about animations until now. Either way, the information in this series of posts will give you an overview of some common approaches to animating on Android.

Animation APIs

Android already comes with a powerful set of tools for animating. This is typically the first place you should look when deciding how best to implement your animation. Depending on the effect you have in mind, this might be the only place you need to look. Since I think seeing complete examples can be very helpful, I've included with this post a series of demo projects that use many of the features we'll be exploring.

Property Animation

Animating an object requires three basic pieces of information - the object properties you want to animate, the property values to animate between, and the duration the animation should last. Introduced in Android 3.0, the property animation APIs allow you to easily create animations by defining these three pieces of information. You can also leverage some of the APIs more advanced features to create more complex animations using relatively small amounts of actual code. These features include:

  • Animator sets
    Using AnimatorSet, group animations to play simultaneously, sequentially, or after a delay.

Repeat
Repeat an animation a defined number of times or indefinitely. You can also set an animation to play in reverse after it completes.

Time interpolation
Define how a property value should be calculated as a function of elapsed time. The below graph is a depiction of Android's AccelerateDecelerateInterpolator.


Keyframes
A Keyframe allows you to define a property's state at a specified animation time using a time/value pair. You can use this to set object properties at certain intervals of the animation.

Pause and Resume
Added in API 19 (KitKat), ValueAnimator and ObjectAnimator can pause and resume running animations using the pause() and resume() methods. You can listen for these events by implementing and adding AnimatorPauseListener.

Frame refresh delay
Use this to specify the frame rate your animation should run at. This defaults to a delay of 10ms. While the animation will strive for this rate, actual performance is determined by overall system load.

Using these features you can animate nearly any property belonging to almost any object. Some examples of view properties you can animate natively include location, rotation, scale, pivot, alpha, and color. So how exactly can you create these animations? The exact answer depends on what you'll be animating and personal preference, but you have the choice of using two classes, both of which extend the Animator class: ValueAnimator and ObjectAnimator.

ValueAnimator

As the name suggests, ValueAnimator modifies values of some type over a set duration. Out of the box you can animate int, float, and color types, but you can also implement the TypeEvaluator interface to support others. Modifying a value by itself will not create an animation. In order to apply the animating values to your object, you must listen for when the values are updated. This is accomplished by implementing callback interfaces.

The two listeners supported by all Animator subclasses are AnimatorUpdateListener and AnimatorListener. The latter is optional, but if you want to be notified when your value is updated you must implement AnimatorUpdateListener. The below code demonstrates a simple implementation of ValueAnimator being used with AnimatorUpdateListener:

public AnimatedView() {
	ValueAnimator animator = ValueAnimator.ofInt(0, 100);
	animator.setDuration(2000);
	animator.setInterpolator(new LinearInterpolator());
 	animator.addUpdateListener(this);
	animator.start();
}
 
@Override
public void onAnimationUpdate (ValueAnimator animation) {
	// AnimatorUpdateListener method
	// Apply updated value to object
	xPos = animation.getAnimatedValue();
	invalidate();
}
 
@Override
protected void onDraw(Canvas canvas) {
	// Calling invalidate() in onAnimationUpdate()
	// will ask Android to re-draw the view
	// Use xPos when drawing to canvas… 
}

Here we use ValueAnimator's static ofInt(int, int) method to get a ValueAnimator instance set to animate an integer from 0 to 100. If we wanted to animate our own type, we could instead get an instance from the static ofObject(TypeEvaluator, Object… ) method. After getting a ValueAnimator, we set up its animation properties. For this example the duration is set for two seconds and the interpolator is set so the animation will be a constant speed. Once our properties are set we just provide our AnimatorUpdateListener and call start().

After start() is called, onAnimationUpdate(ValueAnimator) will execute with every new frame of our animation. Within onAnimationUpdate(ValueAnimator) we retrieve our new integer value using getAnimatedValue() and apply it to our object. Next we'll look at how to use ObjectAnimator so we don't have to handle applying the value ourselves.

ObjectAnimator

ObjectAnimator is a subclass of ValueAnimator that combines the process of modifying a value and then applying that value to a defined object property. For some implementations, this will eliminate the need for AnimatorUpdateListener since we no longer need to listen for value changes. This can result in cleaner code, but will only work if the target object is compatible with ObjectAnimator.

For ObjectAnimator to work correctly, you must know the name of the property you want to animate, and the object containing that property must have a setter method of the format "set{PropertyName}()". Once we meet this requirement, getting an ObjectAnimator instance is as simple as:

ObjectAnimator.ofFloat(objectInstance, "alpha", 0, 1);

The above code returns an ObjectAnimator instance that will animate the alpha property of the provided object between float values 0 and 1. As we just discussed, objectInstance must have a setAlpha(float) method or this will just silently fail to animate. Once we've obtained our ObjectAnimator instance, all that's left to do is set the duration using setDuration(int) and calling start() to run the animation.

Additional Features

In addition to what we discussed above, property animations have a few other features and uses that make them a powerful tool when animating. These include:

  • Animating Layout Changes
    Property animations can be used to animate views when their visibility changes. You can animate a single view as its visibility changes between VISIBLE and GONE or animate a ViewGroup as children are added and removed. This is accomplished by passing an Animator to a LayoutTransition object and defining when the animation should run.

Animating Fragments
If you're not using the support library fragments, you can use animators to define how a fragment should animate in and out of view. Just use the appropriate FragmentTransition.setCustomAnimations() method before committing a fragment addition or replacement. If you are using the support library fragments, you can use the Animation classes we'll look at next.

ViewPropertyAnimator
When animating multiple properties of a single view simultaneously, we can use AnimatorSet as mentioned at the beginning of this section, but a better approach is to use ViewPropertyAnimator. Where AnimatorSet requires us to create an animator for each property, ViewPropertyAnimator can optimize the same task using a single line of code. The main drawback to this API is it wasn't introduced until Android 3.1.

Declare in XML
ValueAnimator, ObjectAnimator, and AnimatorSet can be declared both programmatically and with XML. Using XML may help increase maintainability while allowing you to more easily reuse and rearrange animations.

View Animation

View animations are used to apply transformations to View objects and are supported all the way back to API level one. The animations available extend the Animation class and include translate, rotate, scale, and alpha. If you would like to create your own view animation, simply extend the Animation class and apply your transformation in the applyTransformation(float, Transformation) method. When we compare this functionality to that of property animations, we can already see some shortcomings. With property animation we can very easily animate just about any property of any object. View animations are limited to animating the attributes listed above unless we want to create our own class, and even then the animations can only be applied to objects extending View.

When creating an animation, you will need to supply information specific to that type of transformation. This can include a range of start and end values such as position, scale, degree, duration, interpolator, and more. Some of these values can be exact screen coordinates or degrees while others can be relative to itself or to its parent. The Android documentation contains more information about what each transformation requires. Just like with property animations, this information can be created programmatically or in XML and can be grouped together using an AnimationSet. One advantage view animation does have is its ability to define relative distances, where property animations must be defined using exact values.

Perhaps the biggest drawback to view animation is at the core of how it works. The transformations performed do not actually change the properties of the view, but rather only modifies how the view draws itself. This can create some strange effects, such as touch events registering where the view doesn't appear to be. Additionally, the transformation cannot go beyond the bounds of the parent ViewGroup, or the animation will be clipped. The Android documentation elaborates on how a view may draw itself while animating:


"Regardless of how your animation may move or resize, the bounds of the View that holds your animation will not automatically adjust to accommodate it. Even so, the animation will still be drawn beyond the bounds of its View and will not be clipped. However, clipping will occur if the animation exceeds the bounds of the parent View."

Property animations resolve this by modifying the actual properties of the object, not just how the object appears.

According to Google's documentation, if view animations can accomplish your desired effect there is no advantage to using property animations, but you may want to consider all limitations before deciding what approach to take.

Now that we have an understanding of what view animations can do, lets take a look at some sample code in an XML file we'll name "anim_translate.xml":

 android:duration="300"
android:fromXDelta="0"
android:fromYDelta="0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toXDelta="500"
android:toYDelta="0" />

This XML sets up a simple translate animation that will move a view 500 pixels to the right in 300 milliseconds. Now all that's left is to tell a view to execute this animation.

translateButton.setOnClickListener(new OnClickListener() {
	@Override
	public void onClick(View v) {
		Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.anim_translate);
		v.startAnimation(animation);
	}
});

Another use for these animations involves fragments. If you're using the support library fragments, you can use them to define how your fragments animate in and out of view. Simply use the FragmentTransition.setCustomAnimations() method before committing fragment additions or replacements.

FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.anim_slide_in, R.anim.anim_slide_out);
ft.replace(R.id.fragment_container, new MyFragment());
ft.commit();

Drawable Animation

Drawable animations require you to provide each frame of the animation as a resource. Think of this as a roll of film - what appears to be one movement is actually individual frames displaying one after another. With drawable animations you define what each frame will display and for how long. This approach is not well suited for smooth translations, but can be a great solution for creating simple effects.

Like the other techniques we've discussed, you can define this animation programmatically or with XML. To get a better idea of how this works, lets look at a simple XML example:




Our example above consists of an animation-list root element and child item elements. Each of the item elements represents a single frame in our animation. Each of these frames has two properties - the drawable resource to display and the duration to display it for. The animation-list element has a property called oneshot that, when set to false, will cause our animation to loop indefinitely. If we instead set this to true, the animation will run once and freeze on the last item.

Once your animation is defined, you can set it to be the background of a view just like any other resource. From there, starting the animation is as simple as:

AnimationDrawable animationDrawable = (AnimationDrawable) findViewById(R.id.animation_layout).getBackground();
animationDrawable.start();

One special note - because this relies on your view being inflated, you cannot start the animation until after onCreate() has executed. If you want to start the animation without any user interaction, just call start() in your activity's onWindowFocusChanged() method. Check out the included drawable animation demo for an example of this.

Custom Animations

If you read the above overviews, you now have a good understanding of the tools Android provides so you can easily add animations to your app. In most cases these APIs will be powerful enough to create whatever effect you have in mind, but not always. In the second part of this post we'll explore how you can create custom animations outside of what Android's APIs provide.