Adding transitions and playing videos in Android
The Android framework provides two animation systems: property animation (introduced in Android 3.0) and view animation. Both animation systems are viable options, but the property animation system, in general, is the preferred method to use, because it is more flexible and offers more features. In addition to these two systems, you can utilize Drawable animation, which allows you to load drawable resources and display them one frame after another.
Introduced in Android 3.0 (API level 11), the property animation system lets you animate properties of any object, including ones that are not rendered to the screen. The system is extensible and lets you animate properties of custom types as well.
View Animation is the older system and can only be used for Views. It is relatively easy to setup and offers enough capabilities to meet many application's needs.
Drawable animation involves displaying Drawable resources one after another, like a roll of film. This method of animation is useful if you want to animate things that are easier to represent with Drawable resources, such as a progression of bitmaps.
The property animation system is a robust framework that allows you to animate almost anything. You can define an animation to change any object property over time, regardless of whether it draws to the screen or not. A property animation changes a property's (a field in an object) value over a specified length of time. To animate something, you specify the object property that you want to animate, such as an object's position on the screen, how long you want to animate it for, and what values you want to animate between.
The property animation system lets you define the following characteristics of an animation:
- Duration: You can specify the duration of an animation. The default length is 300 ms.
- Time interpolation: You can specify how the values for the property are calculated as a function of the animation's current elapsed time.
- Repeat count and behavior: You can specify whether or not to have an animation repeat when it reaches the end of a duration and how many times to repeat the animation. You can also specify whether you want the animation to play back in reverse. Setting it to reverse plays the animation forwards then backwards repeatedly, until the number of repeats is reached.
- Animator sets: You can group animations into logical sets that play together or sequentially or after specified delays.
- Frame refresh delay: You can specify how often to refresh frames of your animation. The default is set to refresh every 10 ms, but the speed in which your application can refresh frames is ultimately dependent on how busy the system is overall and how fast the system can service the underlying timer.
How Property Animation Works
First, let's go over how an animation works with a simple example. Figure 1 depicts a hypothetical object that is animated with its
xproperty, which represents its horizontal location on a screen. The duration of the animation is set to 40 ms and the distance to travel is 40 pixels. Every 10 ms, which is the default frame refresh rate, the object moves horizontally by 10 pixels. At the end of 40ms, the animation stops, and the object ends at horizontal position 40. This is an example of an animation with linear interpolation, meaning the object moves at a constant speed.
You can also specify animations to have a non-linear interpolation. Figure 2 illustrates a hypothetical object that accelerates at the beginning of the animation, and decelerates at the end of the animation. The object still moves 40 pixels in 40 ms, but non-linearly. In the beginning, this animation accelerates up to the halfway point then decelerates from the halfway point until the end of the animation. As Figure 2 shows, the distance traveled at the beginning and end of the animation is less than in the middle.
Let's take a detailed look at how the important components of the property animation system would calculate animations like the ones illustrated above. Figure 3 depicts how the main classes work with one another.
ValueAnimatorobject keeps track of your animation's timing, such as how long the animation has been running, and the current value of the property that it is animating.
TimeInterpolator, which defines animation interpolation, and a
TypeEvaluator, which defines how to calculate values for the property being animated. For example, in Figure 2, the
TimeInterpolatorused would be
To start an animation, create a
ValueAnimatorand give it the starting and ending values for the property that you want to animate, along with the duration of the animation. When you call
start()the animation begins. During the whole animation, the
ValueAnimatorcalculates an elapsed fraction between 0 and 1, based on the duration of the animation and how much time has elapsed. The elapsed fraction represents the percentage of time that the animation has completed, 0 meaning 0% and 1 meaning 100%. For example, in Figure 1, the elapsed fraction at t = 10 ms would be .25 because the total duration is t = 40 ms.
ValueAnimatoris done calculating an elapsed fraction, it calls the
TimeInterpolatorthat is currently set, to calculate an interpolated fraction. An interpolated fraction maps the elapsed fraction to a new fraction that takes into account the time interpolation that is set. For example, in Figure 2, because the animation slowly accelerates, the interpolated fraction, about .15, is less than the elapsed fraction, .25, at t = 10 ms. In Figure 1, the interpolated fraction is always the same as the elapsed fraction.
When the interpolated fraction is calculated,
ValueAnimatorcalls the appropriate
TypeEvaluator, to calculate the value of the property that you are animating, based on the interpolated fraction, the starting value, and the ending value of the animation. For example, in Figure 2, the interpolated fraction was .15 at t = 10 ms, so the value for the property at that time would be .15 X (40 - 0), or 6.
com.example.android.apis.animationpackage in the API Demos sample project provides many examples on how to use the property animation system.
How Property Animation Differs from View Animation
The view animation system provides the capability to only animate
Viewobjects, so if you wanted to animate non-
Viewobjects, you have to implement your own code to do so. The view animation system is also constrained in the fact that it only exposes a few aspects of a
Viewobject to animate, such as the scaling and rotation of a View but not the background color, for instance.
Another disadvantage of the view animation system is that it only modified where the View was drawn, and not the actual View itself. For instance, if you animated a button to move across the screen, the button draws correctly, but the actual location where you can click the button does not change, so you have to implement your own logic to handle this.
With the property animation system, these constraints are completely removed, and you can animate any property of any object (Views and non-Views) and the object itself is actually modified. The property animation system is also more robust in the way it carries out animation. At a high level, you assign animators to the properties that you want to animate, such as color, position, or size and can define aspects of the animation such as interpolation and synchronization of multiple animators.
The view animation system, however, takes less time to setup and requires less code to write. If view animation accomplishes everything that you need to do, or if your existing code already works the way you want, there is no need to use the property animation system. It also might make sense to use both animation systems for different situations if the use case arises.
You can find most of the property animation system's APIs in
android.animation. Because the view animation system already defines many interpolators in
android.view.animation, you can use those interpolators in the property animation system as well. The following tables describe the main components of the property animation system.
Animatorclass provides the basic structure for creating animations. You normally do not use this class directly as it only provides minimal functionality that must be extended to fully support animating values. The following subclasses extend
The main timing engine for property animation that also computes the values for the property to be animated. It has all of the core functionality that calculates animation values and contains the timing details of each animation, information about whether an animation repeats, listeners that receive update events, and the ability to set custom types to evaluate. There are two pieces to animating properties: calculating the animated values and setting those values on the object and property that is being animated.
ValueAnimatordoes not carry out the second piece, so you must listen for updates to values calculated by the
ValueAnimatorand modify the objects that you want to animate with your own logic. See the section about Animating with ValueAnimator for more information.
A subclass of
ValueAnimatorthat allows you to set a target object and object property to animate. This class updates the property accordingly when it computes a new value for the animation. You want to use
ObjectAnimatormost of the time, because it makes the process of animating values on target objects much easier. However, you sometimes want to use
ObjectAnimatorhas a few more restrictions, such as requiring specific acessor methods to be present on the target object.
|Provides a mechanism to group animations together so that they run in relation to one another. You can set animations to play together, sequentially, or after a specified delay. See the section about Choreographing multiple animations with Animator Sets for more information.
Evaluators tell the property animation system how to calculate values for a given property. They take the timing data that is provided by an
Animatorclass, the animation's start and end value, and calculate the animated values of the property based on this data. The property animation system provides the following evaluators:
The default evaluator to calculate values for
The default evaluator to calculate values for
|The default evaluator to calculate values for color properties that are represented as hexidecimal values.
An interface that allows you to create your own evaluator. If you are animating an object property that is not an
float, or color, you must implement the
TypeEvaluatorinterface to specify how to compute the object property's animated values. You can also specify a custom
float, and color values as well, if you want to process those types differently than the default behavior. See the section about Using a TypeEvaluator for more information on how to write a custom evaluator.
A time interpolator defines how specific values in an animation are calculated as a function of time. For example, you can specify animations to happen linearly across the whole animation, meaning the animation moves evenly the entire time, or you can specify animations to use non-linear time, for example, accelerating at the beginning and decelerating at the end of the animation. Table 3 describes the interpolators that are contained in
android.view.animation. If none of the provided interpolators suits your needs, implement the
TimeInterpolatorinterface and create your own. See Using interpolators for more information on how to write a custom interpolator.
|An interpolator whose rate of change starts and ends slowly but accelerates through the middle.
|An interpolator whose rate of change starts out slowly and then accelerates.
|An interpolator whose change starts backward then flings forward.
|An interpolator whose change starts backward, flings forward and overshoots the target value, then finally goes back to the final value.
|An interpolator whose change bounces at the end.
|An interpolator whose animation repeats for a specified number of cycles.
|An interpolator whose rate of change starts out quickly and and then decelerates.
|An interpolator whose rate of change is constant.
|An interpolator whose change flings forward and overshoots the last value then comes back.
|An interface that allows you to implement your own interpolator.
Animating with ValueAnimator
ValueAnimatorclass lets you animate values of some type for the duration of an animation by specifying a set of
float, or color values to animate through. You obtain a
ValueAnimatorby calling one of its factory methods:
ofObject(). For example:
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f); animation.setDuration(1000); animation.start();
In this code, the
ValueAnimatorstarts calculating the values of the animation, between 0 and 1, for a duration of 1000 ms, when the
You can also specify a custom type to animate by doing the following:
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue); animation.setDuration(1000); animation.start();
In this code, the
ValueAnimatorstarts calculating the values of the animation, between
endPropertyValueusing the logic supplied by
MyTypeEvaluatorfor a duration of 1000 ms, when the
The previous code snippets, however, has no real effect on an object, because the
ValueAnimatordoes not operate on objects or properties directly. The most likely thing that you want to do is modify the objects that you want to animate with these calculated values. You do this by defining listeners in the
ValueAnimatorto appropriately handle important events during the animation's lifespan, such as frame updates. When implementing the listeners, you can obtain the calculated value for that specific frame refresh by calling
getAnimatedValue(). For more information on listeners, see the section about Animation Listeners.
Animating with ObjectAnimator
ObjectAnimatoris a subclass of the
ValueAnimator(discussed in the previous section) and combines the timing engine and value computation of
ValueAnimatorwith the ability to animate a named property of a target object. This makes animating any object much easier, as you no longer need to implement the
ValueAnimator.AnimatorUpdateListener, because the animated property updates automatically.
ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f); anim.setDuration(1000); anim.start();
To have the
ObjectAnimatorupdate properties correctly, you must do the following:
The object property that you are animating must have a setter function (in camel case) in the form of
set. Because the
ObjectAnimatorautomatically updates the property during animation, it must be able to access the property with this setter method. For example, if the property name is
foo, you need to have a
setFoo()method. If this setter method does not exist, you have three options:
- Add the setter method to the class if you have the rights to do so.
- Use a wrapper class that you have rights to change and have that wrapper receive the value with a valid setter method and forward it to the original object.
If you specify only one value for the
values...parameter in one of the
ObjectAnimatorfactory methods, it is assumed to be the ending value of the animation. Therefore, the object property that you are animating must have a getter function that is used to obtain the starting value of the animation. The getter function must be in the form of
get. For example, if the property name is
foo, you need to have a
The getter (if needed) and setter methods of the property that you are animating must operate on the same type as the starting and ending values that you specify to
ObjectAnimator. For example, you must have
targetObject.getPropName(float)if you construct the following
ObjectAnimator.ofFloat(targetObject, "propName", 1f)
Depending on what property or object you are animating, you might need to call the
invalidate()method on a View force the screen to redraw itself with the updated animated values. You do this in the
onAnimationUpdate()callback. For example, animating the color property of a Drawable object only cause updates to the screen when that object redraws itself. All of the property setters on View, such as
setTranslationX()invalidate the View properly, so you do not need to invalidate the View when calling these methods with new values. For more information on listeners, see the section about Animation Listeners.
Choreographing Multiple Animations with AnimatorSet
In many cases, you want to play an animation that depends on when another animation starts or finishes. The Android system lets you bundle animations together into an
AnimatorSet, so that you can specify whether to start animations simultaneously, sequentially, or after a specified delay. You can also nest
AnimatorSetobjects within each other.
stretchAnim2at the same time.
AnimatorSet bouncer = new AnimatorSet(); bouncer.play(bounceAnim).before(squashAnim1); bouncer.play(squashAnim1).with(squashAnim2); bouncer.play(squashAnim1).with(stretchAnim1); bouncer.play(squashAnim1).with(stretchAnim2); bouncer.play(bounceBackAnim).after(stretchAnim2);