May 8, 2011

View Animation In Android Using ListView



Android exposes the transformation matrix for a view by allowing us to register an animation object with the view. The animation object will have a callback that lets it obtain the current matrix for a view and change it in some manner to arrive at a new view.
Let's start by planning an example for animating a view. We'll begin with an activity where we'll place a ListView with a few items. Then, we will create a button at the top of the screen to start the ListView animation when clicked.
Let's look at the layout file, /res/list_layout.xml
<?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/btn_animate"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="Start Animation"/>
   <ListView
      android:id="@+id/list_view_id"
      android:persistentDrawingCache=
  "animation|scrolling"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"/>
</LinearLayout>
The layout has two parts: the first is the button named btn_animate to animate a view, and the second part is the ListView, which is named list_view_id.
Now we have the layout for the activity, we can create the activity to show the view:
ViewAnimation.java
package com.bogotobogo.viewanimation;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;

public class ViewAnimation extends Activity 
{
 @Override
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);
  setContentView(R.layout.list_layout);
  setupListView();
  this.setupButton();
 }

 private void setupListView(){
  String[] listItems = new String[] {
   "Item 1", "Item 2", "Item 3",
   "Item 4", "Item 5", "Item 6",
  };
  ArrayAdapter listItemAdapter =
   new ArrayAdapter(this
     ,android.R.layout.simple_list_item_1
     ,listItems);
             
  ListView lv = (ListView)this.findViewById(R.id.list_view_id);
  lv.setAdapter(listItemAdapter);
 }
    
 private void setupButton(){
  Button b = (Button)this.findViewById(R.id.btn_animate);
  b.setOnClickListener(
    new Button.OnClickListener(){
     public void onClick(View v) {
      animateListView();
     }
    });
 }
    
 private void animateListView() {
  ListView lv = (ListView)this.findViewById(R.id.list_view_id);
  ViewAnim animation = new ViewAnim();
  lv.startAnimation(animation);
 }
}
We have loaded the view and set up the ListView to contain six text items. We've set up the button in such a way that it would call animate() when clicked.
We can invoke this activity as long as we register it in the AndroidManifest.xml file:
<activity android:name=".ViewAnimation"
                  android:label="@string/app_name">
We want to add animation to the ListView. So, we need a class that derives from android.view.animation.Animation. We then need to override the applyTransformation method to modify the transformation matrix.
Let's call this derived class ViewAnim
ViewAnim.java
package com.bogotobogo.viewanimation;

import android.graphics.Matrix;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;

public class ViewAnim extends Animation
{
 public void ViewAnimation2(){}

 @Override
 public void initialize(int width, int height, int parentWidth,
                                 int parentHeight) {
  super.initialize(width, height, parentWidth, parentHeight);
  setDuration(2500);
  setFillAfter(true);
  setInterpolator(new LinearInterpolator());
 }

 @Override
 protected void applyTransformation(float interpolatedTime, Transformation t){
  final Matrix matrix = t.getMatrix();
  matrix.setScale(interpolatedTime, interpolatedTime);
 }
}
Once we have the ViewAnim class, we can do:
ListView lv = (ListView)this.findViewById(R.id.list_view_id);
  ViewAnim animation = new ViewAnim();
as in the animateListView() method.
Let's look at the class more carefully.
The initialize() method ia s callback method that tells us about the dimensions of the view. This is also a place to initialize any animation parameters we might have.
The main part of the animation occurs in the applyTransformation() method. The Android framework will call this method again and again to do animation. Every time Android calls the method, interpolatedTime has a different value. This parameter changes from 0 to 1 depending on where we are in the 2.5 second duration that we set during initialization.
We want to change the transformation matrix that is available through the transformation object called t in the applyTransformation() method. We will first get the matrix and change something about it. When the view gets painted, the new matrix will take effect.
The setScale() method takes two parameters: the scaling factor in the x direction and the scaling factor in the y direction.
matrix.setScale(interpolatedTime, interpolatedTime);
Because the interpolatedTime goes between 0 and 1, we can use that value directly as the scaling factor. So when we start the animation, the scaling factor is 0 in both x and y directions.


Here are some snapshots during the animation.
ViewAnimA ViewAnimB
ViewAnimC ViewAnimD

Files used in this View Animation example, ViewAnimation.zip

1 comment: