Android Property Animations: Programming Animations

In the previous post on property animations I introduced the ObjectAnimator to create animations on arbitrary properties on objects. The only restriction is that the object must define a setter method for the property that should be animated. ObjectAnimator extends the abstract Animator class which forms the basis of the Property Animation System. The system defines three other Animator classes, the AnimatorSet , the ValueAnimator and the TimeAnimator . In practice you will rarely have the need for the latter two and the ObjectAnimator together with the AnimatorSet should be sufficient. In this post I will show you how to programmatically create animations using these two classes. The ValueAnimator and the TimeAnimator will be the topic of a later post.

Object Animator

The ObjectAnimator class defines a collection of static factory methods that allow you to create standard object animations in a single line of code. Recall the example given in the introduction to property animations. We created an animation that rotated a view around its vertical axis. In order to achieve the same result programmatically, without the need to create a separate XML resource file containing the animation. Simply replace the flipOnVertical method with the following code.

public void flipOnVertical(View view) { View image = findViewById(R.id.some_image); ObjectAnimator anim = ObjectAnimator.ofFloat(image, "rotationY", 0.0f, 360.0f); anim.setDuration(300); anim.start(); }

As you can see, the code is not much longer than before. You will find this to be the case in most animations and you will rarely find a need for writing animation resource files. The important method in the code above is the static method ofFloat , defined by ObjectAnimator . The method is a simple static factory method that creates an ObjectAnimator for you. The first argument of the method is the object that should be animated. The second argument id the name of the parameter that should be changed inside the object. The object will need to have a setter method for the property in order for the animation to work. This means for the property “rotationY” there has to be a method setRotationY defined by the image object. This method should accept float values for is argument. The values that follow the property name are the start and end values for the animation. The ofFloat method allows you to specify not only two values but an arbitrary number of intermediate values. The ObjectAnimator will then take all the values in sequence and arrange them at equal time intervals and interpolate between them. You can think of the values as way-points that the animator will pass at regular time intervals. I modify the previous example to illustrate this.

public void disappearBox(View view){ View image = findViewById(R.id.policebox); ObjectAnimator anim = ObjectAnimator.ofFloat(image, "alpha", 1.0f, 0.25f, 0.75f, 0.15f, 0.5f, 0.0f); anim.setDuration(5000); anim.start(); }

I have changed the property name to “alpha” and created a list of alpha values that alternate between decreasing and increasing. The duration of the animation has been changed to 5s=5000 milliseconds. This is done by calling the setDuration method. I have also changed the image to be animated to depict an old fashioned UK police box and updated the method name to disappearBox . The onClick callback in the layout file should be changed accordingly. The resulting animation can be seen on the right.

Setting Interpolators

You can set interpolators to use with the animation, just as you could with view animations. The interpolators of the View Animation System can be reused for this purpose. By default the Animator uses the AccelerateDecelerateInterpolator . To make the example above more realistic just add the following line before starting the animation.

anim.setInterpolator(new LinearInterpolator());

Available Interpolators are

LinearInterpolator



AccelerateDecelerateInterpolator



AccelerateInterpolator



AnticipateInterpolator



AnticipateOvershootInterpolator



BounceInterpolator



CycleInterpolator



DecelerateInterpolator



LinearInterpolator



OvershootInterpolator

For details on the interpolators, and on how to write your own, see the post on interpolators.

Animator Set

Up to now, I have just described how to use the ObjectAnimator to animate a single property of an object. In many cases you want to modify multiple properties at the same time. This can be done using animator sets. The AnimatorSet class allows you to specify multiple animation to run in parallel. You can define an animator set inside an XML resource file using the animatorSet tag. But the real power of the animator set only comes to light when you use the animator set programmatically. You can add Animator objects and play them in a specific order. In addition, all the animators can modify properties on a different objects. In this way you can create an animation that animates multiple views at the same time. Let’s extend the example above and create a second animation.

public void disappearBox(View view) { View policebox = findViewById(R.id.policebox); View policeboxlight = findViewById(R.id.policeboxlight); ObjectAnimator anim1 = ObjectAnimator.ofFloat(policebox, "alpha", 1.0f, 1.0f, 0.25f, 0.75f, 0.15f, 0.5f, 0.0f); ObjectAnimator anim2 = ObjectAnimator.ofFloat(policeboxlight, "alpha", 0.0f, 1.0f, 0.0f, 0.75f, 0.0f, 0.5f, 0.0f);

The second animation acts on a different image where it also modifies the alpha value. In order to play both of these animations together, you have to create an animator set. You can simply create one using new .

AnimatorSet animSet = new AnimatorSet();

Now you have to specify which animations to include in the set and in what order to play them. You can use the playTogether and playSequentially methods. In our case, we want to play both animations at the same time, so we use playTogether .

animSet.playTogether(anim1, anim2);

Both methods take an arbitrary number of Animator objects. playTogether also accepts a Collection<Animator> and playSequentially accepts a List<Animator> . The difference arises because the order is matters when animations are played sequentially but doesn’t when they are played together. The rest of the code follows the same pattern as before. We set the duration and the interpolator on the animator set and then start the animation.

animSet.setDuration(5000); animSet.setInterpolator(new LinearInterpolator()); animSet.start(); }

The result of our little animation can be seen on the right. In the next post on property animations I will talk more about animator sets and using the AnimatorSet.Builder class to choreograph animations in a more complex way.

The code for this tutorial can be found on github.

Follow the author

Image of the police box is distributed under the Creative Commons Attribution-Share Alike 3.0 Unported license. Copyright Dan Sellers.