This is the second post on Android Property Animation. Previous post can be found below.
ValueAnimator is the core of the Property Animation system. It provides a timing engine which calculates the animation values. It also allows us to get notified at every animation frame through ValueAnimator.AnimatorUpdateListener interface.
All animations created by Property Animation system share a single timing pulse, which is maintained by a custom static handler AnimationHandler at ValueAnimator class. Below is the code extracted from NineOldAndroids library ValueAnimator class.
The handler only handles two types of messages, including ANIMATION_START and ANIMATION_FRAME.
ANIMATION_START message is generated when an animation starts, the handler will receive the message and put the animation into delay queue. Next the handler decide if the animations from the delay queue should be started immediately (add to ready queue). The handler will then process all active animations, which includes those in the ready queue.
ANIMATION_FRAME message is sent by the handler itself to schedule next animation frame update. The handler checks if any animation from the delay queue should be started and then process all active animations. (The code to handle ANIMATION_FRAME is actually part of the code for handling ANIMATION_START).
The handler also checks if an animation should be ended or not in the handler.
By using this static handler, all animations are synchronized on a frame by frame basis.
Animating a single value with ValueAnimator is straightforward. ValueAnimator provides static method like ofInt and ofFloat to animation between integer and floating point values. We will skip that and discuss how to animation multiple values.
Suppose we need to animate an ImageView of a red square from bottom left to top right as shown in the screenshots below.
Figure 1. Animation Bottom Left to Top Right
It is obvious that we need to update both the x and y coordinates. The naive approach is to create two animations and play them simultaneously, but it is not efficient. We can use PropertyValuesHolder to combine multiple values. Alternatively, we can use custom objects as animation values. We’ll explore both approaches.
We will use the layout as indicated by the xml file below. We want to move the ImageView inside the FrameLayout with id “container”.
PropertyValuesHolder contains information about a property and its values during animation. It is used with ValueAnimator or ObjectAnimator to animate multiple properties at the same time.
In order to support property animation in pre-3.0 Android devices, NineOldAndroids provide a class AnimatorProxy to wrap a view and handles drawing of animated views. We need to wrap the ImageView in our code as below.
The code below creates an animation which animates two values which represent X and Y position of the image view with respective to the frame layout.
We use two PropertyValuesHolder to animate two values named posX and posY. We then created the animation using ValueAnimator. We registered the listener, set the duration and start the animation. The listener interface is implemented by overriding the onAnimationUpdate callback function as below.
We retrieve the animated values posX and posY at every animation frame and update it.
Using Custom Objects as Animation Values
ValueAnimator can be used to animate custom objects also. We’ll need to specify a TypeEvaluator to tell the ValueAnimator how the values should be calculated.
In our example, we are moving the position of the ImageView, so we can create a custom object to represent the position of the ImageView and animate it. The code below creates a class Position to represent the position of the ImageView.
We also provide to TypeEvaluator by implementing the android.animation.TypeEvaluator<T> interface.
At every animation frame, the callback function evaluate will be triggered with three arguments, including the elapsed time so far, the animation start position and end position. We can calculate the current position should be based on the three input arguments and returns it.
With the custom object and TypeEvaluator in place, the animation can be easily created as below.
Of course, we still need to implement the ValueAnimator.AnimatorUpdateListener interface.
Note that we can also use ViewPropertyAnimator, which I’ll cover in another post if I got time.
You can get the full source code here: https://github.com/roman10/roman10-android-tutorial/tree/master/PropertyAnimation
Android ValueAnimator doc: http://developer.android.com/reference/android/animation/ValueAnimator.html