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:

1
2
3
4
5
6
7
8
9
<?xml version="1.0"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent" android:layout_height="match_parent"
	android:orientation="vertical" android:gravity="center">
	<TextView android:text="Page 1" android:layout_width="wrap_content"
		android:layout_height="wrap_content" />
	<Button android:layout_height="wrap_content" android:text="Next"
		android:layout_width="wrap_content" android:id="@+id/NextButton" />
</LinearLayout>

and at res/layout/second.xml:

1
2
3
4
5
6
7
8
9
<?xml version="1.0"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent" android:layout_height="match_parent"
	android:orientation="vertical" android:gravity="center">
	<TextView android:text="Page 2" android:layout_width="wrap_content"
		android:layout_height="wrap_content" />
	<Button android:layout_height="wrap_content" android:text="Back"
		android:layout_width="wrap_content" android:id="@+id/BackButton" />
</LinearLayout>

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="com.stylingandroid.Animation" android:versionCode="1"
	android:versionName="1.0">
	<uses-sdk android:minSdkVersion="10" />
 
	<application android:icon="@drawable/icon" android:label="@string/app_name">
		<activity android:label="@string/app_name" android:name=".FirstActivity">
			<intent-filter>
				<action android:name="android.intent.action.MAIN" />
				<category android:name="android.intent.category.LAUNCHER" />
			</intent-filter>
		</activity>
		<activity android:name=".SecondActivity"></activity>
	</application>
</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:

1
2
3
4
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
	android:fromXDelta="100%p" android:toXDelta="0%p"
	android:duration="@android:integer/config_longAnimTime"/>

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:

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
	android:fromXDelta="0" android:toXDelta="-100%p"
	android:duration="@android:integer/config_longAnimTime" />
</set>

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@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:

1
2
3
4
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
	android:fromXDelta="-100%p" android:toXDelta="0%p"
	android:duration="@android:integer/config_longAnimTime" />

and res/anim/slide_out_right.xml:

1
2
3
4
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
	android:fromXDelta="0" android:toXDelta="100%p"
	android:duration="@android:integer/config_longAnimTime" />

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@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. This article originally appeared on Styling Android.

Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License

Send the author to the moon!

Creative Commons License
Simple Animation – Part 1 by Styling Android, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Terms and conditions beyond the scope of this license may be available at blog.stylingandroid.com.

8 Responses to “Simple Animation – Part 1”

  1. Ekta GUpta says:

    Thanks… The blog is really good. very well explained

  2. Steven says:

    Nice and easy-to-understand transition. Thanks

  3. Peter says:

    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

  4. ayush says:

    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);
    }

  5. Noman says:

    Not working… just a simple button it has…

  6. Saurabh says:

    Really Great Tutorial… with great explaination.

  7. seso says:

    Thanks for sharing. It is great and easy tutorial : )

  8. ajay singh says:

    really Nice and easy-to-understand. Thanks

Leave a Reply