Translate

Simple Animation – Part 1

In this article we are going to be covering some simple animations in Android. In Honeycomb, Google introduced some new animation functionality, however given the relative scarcity of Honeycomb devices, we’ll focus on the animation tools that are available in earlier version of Android.

Firstly, it’s not going to be possible to provide examples of how these animations will look. I’ve played with some apps which claim to capture video via adb,but the frame rate simply isn’t good enough to be worthwhile. So I suggest that you work along if you want to actually see the animations working.

Secondly, there is no alternative but to use a real device, preferably one with a reasonably fast processor. I have tried developing animations using the emulator but, once again, the frame rate is so slow that the animation is over before the second frame has rendered!

OK, let’s begin by creating a new 2.3.3 Project called Animation, with a package name of “com.stylingandroid.Animation”. We need to create two layouts at res/layout/first.xml:



	
	

and at res/layout/second.xml:



	
	

Next we’ll need to create two activities one named FirstActivity:

package com.stylingandroid.Animation;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class FirstActivity extends Activity
{
	@Override
	protected void onCreate( Bundle savedInstanceState )
	{
		super.onCreate( savedInstanceState );
		setContentView( R.layout.first );
		((Button)findViewById( R.id.NextButton )).setOnClickListener( new OnClickListener()
		{
			@Override
			public void onClick( View v )
			{
				startActivity( new Intent( FirstActivity.this, SecondActivity.class ) );
			}
		});
	}
}

and the other named SecondActivity:

package com.stylingandroid.Animation;

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

public class SecondActivity extends Activity
{
	@Override
	protected void onCreate( Bundle savedInstanceState )
	{
		super.onCreate( savedInstanceState );
		setContentView( R.layout.second );
		((Button)findViewById( R.id.BackButton )).setOnClickListener( new OnClickListener()
		{
			@Override
			public void onClick( View v )
			{
				finish();
			}
		});
	}
}

And we need to add these two activities to our Manifest:



	

	
		
			
				
				
			
		
		
	

Hopefully this should be easy enough to understand: We’ve defined two layouts, each containing some text and a button. We’ve then defined a couple of activities to match these layouts, and wired up the buttons to transition between the two, while remaining back key friendly.

If you try this, you’ll see that the this works as expected, and Android provides a default animation as one activity transitions to the other. While it’s very quick, the actual transition consists of both movement of the two activities, and also a fade between the two.

But what if we want to change this transition? To start with we need to define some animations which control how both the incoming and outgoing activities are animated. Let’s start by creating a new animation in res/anim/slide_in_left.xml:



This defines a simple transition which will move the left edge of the incoming view from the right hand edge of the screen and finish at the left hand edge. It uses one of the pre-defined transition times to control how long the transition should take. We’ll now create another animation in res/anim/slide_out_left.xml:




This will move the left edge of the outgoing view from the left edge of the screen and finish at a distance equal to the screen width off the left hand side of the screen.

If we combine these two animations, it will move the existing view off the screen to the left while moving the new view on from the right. We now need to implement this in src/com/stylingandroid/Animation/FirstActivity.java:

@Override
protected void onCreate( Bundle savedInstanceState )
{
	super.onCreate( savedInstanceState );
	setContentView( R.layout.first );
	((Button)findViewById( R.id.NextButton )).setOnClickListener( new OnClickListener()
	{
		@Override
		public void onClick( View v )
		{
			startActivity( new Intent( FirstActivity.this, SecondActivity.class ) );
			overridePendingTransition( R.anim.slide_in_left, R.anim.slide_out_left );
		}
	});
}

We’ve just added a single line at line 12. What this does is to override the transition using the animations that we’ve just defined. There is one crucial thing about overridePendingTransition: it must be called after startActivity. If we switch the order of these two lines, the transition will not be overridden. There is a clue in the method name in that the transition is not “pending” until we have actually begun the process of navigating to the next activity.

It is worth trying this now because there is currently a clear difference between our new transition and the default one. We have applied our transition to the “Next” button, but the “Back” button still implements the default transition.

But not for long! Let’s define two more animations to perform the reverse transition. First let’s create res/anim/slide_in_right.xml:



and res/anim/slide_out_right.xml:



Then we’ll need to override the pending transition in src/com/stylingandroid/Animation/SecondActivity.java:

@Override
protected void onCreate( Bundle savedInstanceState )
{
	super.onCreate( savedInstanceState );
	setContentView( R.layout.second );
	((Button)findViewById( R.id.BackButton )).setOnClickListener( new OnClickListener()
	{
		@Override
		public void onClick( View v )
		{
			finish();
			overridePendingTransition( R.anim.slide_in_right, R.anim.slide_out_right );
		}
	});
}

Once again, note how the transition is only “pending” once we have started the navigation, after we’ve called finish().

That’s quite nice, but there is one small inconsistency. While on page 2, if we hit the “Back” key on the device rather than hitting the back button on the layout, we’d expect that navigate back to page 1, and it does. However, the transition used for this is sill the default one. We can overcome this by refactoring the contents of onClick into a separate method, and handling the Back key press:

@Override
protected void onCreate( Bundle savedInstanceState )
{
	super.onCreate( savedInstanceState );
	setContentView( R.layout.second );
	((Button)findViewById( R.id.BackButton )).setOnClickListener( new OnClickListener()
	{
		@Override
		public void onClick( View v )
		{
			goBack();
		}
	});
}

private void goBack()
{
	finish();
	overridePendingTransition( R.anim.slide_in_right, R.anim.slide_out_right );
}

@Override
public boolean onKeyUp( int keyCode, KeyEvent event )
{
	if( keyCode == KeyEvent.KEYCODE_BACK )
	{
		goBack();
		return true;
	}
	return super.onKeyUp( keyCode, event );
}

That’s looking quite good. It provides a nice visual transition between the two views, and gives some directional flow which provides the user with a concept of a forward and backward flow through the UI. In the next article we’ll have a look at adding some nice dynamics to the animation.

As usual, the source code for this article can be found here.

© 2011, Mark Allison. All rights reserved.

Copyright © 2011 Styling Android. All Rights Reserved.
Information about how to reuse or republish this work may be available at http://blog.stylingandroid.com/license-information.

8 Comments

  1. Thanks for the nice tutorial.. Appreciated!!

    Quick question,

    Is it possible to do a page flip in Android?? say when I click on Next button the animation should be in such a way we flip the page in the book.. Any pointers?

    Thanks!!

    Peter

  2. For reverse transition, you can also override onBackPressed()..just an alternative.
    @Override
    public void onBackPressed() {
    super.onBackPressed();
    overridePendingTransition(R.anim.slide_in_right,
    R.anim.slide_out_right);
    }

Leave a Reply to seso Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.