Support for animation in Android can be categorized in to three high level topics. These are animating frames, animating views inside a container view such as lists and tables, and animating any general purpose view. The first one is referred to as "Frame by Frame Animation" in Android, the second one is referred to as List animation, and third one is refered to as View Animation. The later two are considered a type of "tweening" animation. In this chapter we will cover each topic using working examples and in depth analysis. We will cover each topic in the order of their difficulty.
Frame by Frame Animation is the simplest of the three to understand. We will start the first section with Frame by Frame Animation where you will know what this type of animation is, how to plan to tell a story using this animation, and how to use AnimationDrawble class to exectue the frames at a certain refresh rate. We will demonstarte Frame by Frame Animation with relevent pictures along with sample code. In the example of this section we will show you how to animate an image of a billiard ball moving along the circumference of a circle.
We will cover the List animation in the second section. It is a bit involved but not as hard as the View animation. In this section we will talk about Scale animation (changing size), Translation Animation (changing position), Rotation Animation (changing orientation), and Alpha Animation (changing color). We will show you how you can declare these animations in an XML file and assoicate the animation ids to a container view such as a list box. We will take a simple list example containing a series of text items and then apply a variety of animation transformations. In this section we will also cover interpolators and also animation sets. Interpolators are used to control the progress of an animation and animation sets are an aggregated set of individual animations.
In the last section we will cover animating a view by changing the transformation matrices. A good understanding of the nature of transformation matrices is critical to this section. We will go through a number of examples to illustrate the behavior of tranformation matrices.Android also introduces the idea of a Camera to simulate the 3D like viewing capabilities. This section covers both these ideas by flipping an image from front to back and back to front in a 3D like animated fashion.
Frame by Frame Animation is the simple process of showing a series of images in succession at quick intervals so that the end effect is that an object in that image will appear to move. This is how movie or film projectors work. In this section we will explore Frame by Frame Animation through an example where we will design an image and save that image as a number of distinct images where each one differs from the other slightly. Then we will take that image and run through the sample code to simulate animation.
Take a look at the following diagram. You see a set of same sized circles with a colored ball on each of the circles. We can take a series of these pictures where the circle is the same size and at the same position but the colored ball is placed at different points along the border of the circle. Once we save 7 or 8 of these frames we can use animation to show that the colored ball is going around the circle.
figure 8-1 Planning for Animation
Let us assume we give a base name for the image as "colored-ball". Then we can store all the 8 images in the "/res/drawable" directory so that we could get access to these images using their resource ids. The name of each image will have the pattern "colored-ball-N" where "N" is the digit.
When we are finsihed with the animation we want the final animation to look like the following figure
figure 8.2 Frame animation in action
The primary area is taken by the amination view. We have included a button to start and stop the animation to observe the behavior of animation. We have also included a debug scratch pad at the top to write any significant events to it as you experiment with this program.
Let us start by creating the basic layout XML for our Activity screen.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:id="@+id/startFAButtonId"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Start Animation"
/>
<ImageView
android:id="@+id/animationImage"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
The first conrol is the debug scratch text control which is a simple text view. We have then added a button to start and stop the animation. The last view is the ImageView where we will play the animation.
Once we have the layout let us create an activity to load this view.
public class FrameAnimationActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.frame_animations_layout);
}
}
you will be able to run this activity from any menu item you may have in your current application by doing the following
Intent intent = new Intent(inActivity,FrameAnimationActivity.class);
inActivity.startActivity(intent);
At this point you will see an activity that looks like the following
figure 3 - sample view
In Android Frame By Frame Animation is accomplished through a class in the graphics package called AnimationDrawable. This class is capable of taking a list of drawable resources (like images) and then render them at the specified intervals. This class is really a thin wrapper to the animation support provided by the basic Drawable class. Drawable class enables animation by asking its container (or on which it draws such as say a View) to invoke a runnable class that essentailly redraws the drawable using a different set of parameters. However these internal implementation details are not necessary to use the AnimationDrawable class. You can look at the AnimationDrawable source code for writing your own animation protocols.
To use this class start with a set of drawable resources placed in the "res/drawable" sub directory. You will then define an XML file that defines the list of frames as below
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/colored-ball1" android:duration="50" />
<item android:drawable="@drawable/colored-ball2" android:duration="50" />
<item android:drawable="@drawable/colored-ball3" android:duration="50" />
<item android:drawable="@drawable/colored-ball4" android:duration="50" />
<item android:drawable="@drawable/colored-ball5" android:duration="50" />
<item android:drawable="@drawable/colored-ball6" android:duration="50" />
<item android:drawable="@drawable/colored-ball7" android:duration="50" />
<item android:drawable="@drawable/colored-ball8" android:duration="50" />
</animation-list>
Each frame points to the coloerd ball images we have assembled through their resource ids. This animation list essentially gets converted into an AnimationDrawable object which itself is set as a background resource for the view. If we assume the filename for this xml file is "frame_animation.xml" residing under "/res/drawable" then you can use the following code to set the AnimationDrawable as the background of the image view
view.setBackGroundResource(Resource.drawable.frame_animation);
Once this is set we can get access to the AnimationDrawable object by doing a "get" on the View object as follows
Object backgroundObject = view.getBackground();
AnimationDrawable ad = (AnimationDrawable)backgroundObject;
Once you have the AnimationDrawable you can use the start() and stop() methods to start and stop the animation. Other important methods on this object include
setOneShot();
addFrame(drawabl, duration);
The method "setOneShot()" runs the animation one time and stops. The method "addFrame()" adds a new frame using a drawable object and sets its duration to be displayed. This is the equivalent of the XML tag "android:duration".
Here is the complete code by putting all this together.
public class FrameAnimationActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.frame_animations_layout);
this.setupButton();
}
private void setupButton()
{
Button b = (Button)this.findViewById(R.id.startFAButtonId);
b.setOnClickListener(
new Button.OnClickListener(){
public void onClick(View v)
{
parentButtonClicked(v);
}
});
}
private void parentButtonClicked(View v)
{
animate();
}
private void animate()
{
ImageView imgView = (ImageView)findViewById(R.id.imageView);
imgView.setVisibility(ImageView.VISIBLE);
imgView.setBackgroundResource(R.drawable.frame_animation);
AnimationDrawable frameAnimation =
(AnimationDrawable) imgView.getBackground();
if (frameAnimation.isRunning())
{
frameAnimation.stop();
}
else
{
frameAnimation.stop();
frameAnimation.start();
}
}
}//eof-class
The method "animate()" locates the image view in the current Activity and sets its background to the AnimationDrawable identified by the resource "R.drawable.frame_animation". The code then retrieves this object and performs animation. The "start/stop" button is setup such that if the animation is running, it will stop and if the animation is in a stopped state it will start.
As a note, if you set the "oneshot" parameter of the animation list to "true" then the animation will stop after doing the animation once. However there is no clearcut way to know that when that happens.