Hi!

Do you know the Transition3d + Rotate3dAnimation from the APIDemos?

I wondered how one could use this animation effect for finishing and starting Activities. Well, this is my solution to it.

*UPDATE 05.12.2011* Working example: ActivitySwitcher

  1. Create a package com.yourapp.animation and copy the Rotate3dAnimation.java in it.
  2. Next, create a new Class yourapp.animation.ActivitySwitcher and implement it like this:

    com.yourapp.animation.ActivitySwitcher.java

    package com.yourapp.animation;
     
    import android.view.Display;
    import android.view.View;
    import android.view.WindowManager;
    import android.view.animation.AccelerateInterpolator;
    import android.view.animation.Animation;
     
    public class ActivitySwitcher {
     
    	private final static int DURATION = 300;
    	private final static float DEPTH = 400.0f;
     
    	/* ----------------------------------------------- */
     
    	public interface AnimationFinishedListener {
    		/**
    		 * Called when the animation is finished.
    		 */
    		public void onAnimationFinished();
    	}
     
    	/* ----------------------------------------------- */
     
    	public static void animationIn(View container, WindowManager windowManager) {
    		animationIn(container, windowManager, null);
    	}
     
    	public static void animationIn(View container, WindowManager windowManager, AnimationFinishedListener listener) {
    		apply3DRotation(90, 0, false, container, windowManager, listener);
    	}
     
    	public static void animationOut(View container, WindowManager windowManager) {
    		animationOut(container, windowManager, null);
    	}
     
    	public static void animationOut(View container, WindowManager windowManager, AnimationFinishedListener listener) {
    		apply3DRotation(0, -90, true, container, windowManager, listener);
    	}
     
    	/* ----------------------------------------------- */
     
    	private static void apply3DRotation(float fromDegree, float toDegree, boolean reverse, View container, WindowManager windowManager, final AnimationFinishedListener listener) {
    		Display display = windowManager.getDefaultDisplay();
    		final float centerX = display.getWidth() / 2.0f;
    		final float centerY = display.getHeight() / 2.0f;
     
    		final Rotate3dAnimation a = new Rotate3dAnimation(fromDegree, toDegree, centerX, centerY, DEPTH, reverse);
    		a.reset();
    		a.setDuration(DURATION);
    		a.setFillAfter(true);
    		a.setInterpolator(new AccelerateInterpolator());
    		if (listener != null) {
    			a.setAnimationListener(new Animation.AnimationListener() {
    				@Override
    				public void onAnimationStart(Animation animation) {
    				}
     
    				@Override
    				public void onAnimationRepeat(Animation animation) {
    				}
     
    				@Override
    				public void onAnimationEnd(Animation animation) {
    					listener.onAnimationFinished();
    				}
    			});
    		}
    		container.clearAnimation();
    		container.startAnimation(a);
    	}
    }
  3. That’s it! Now you can use it like this:

    Activity1.java

    package com.yourapp.activity
     
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import com.yourapp.R;
    import com.yourapp.animation.ActivitySwitcher;
     
    public class Activity1 extends Activity {
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity1);
     
    		Button switchActivityBtn = (Button) findViewById(R.id.bSwitchActivity);
    		switchActivityBtn.setOnClickListener(new View.OnClickListener() {
    			@Override
    			public void onClick(View v) {
    				animatedStartActivity();
    			}
    		});
    	}
     
    	@Override
    	protected void onResume() {
    		// animateIn this activity
    		ActivitySwitcher.animationIn(findViewById(R.id.container), getWindowManager());
    		super.onResume();
    	}
     
    	private void animatedStartActivity() {
    		// we only animateOut this activity here.
    		// The new activity will animateIn from its onResume() - be sure to implement it.
    		final Intent intent = new Intent(getApplicationContext(), Activity2.class);
    		// disable default animation for new intent
    		intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
    		ActivitySwitcher.animationOut(findViewById(R.id.container), getWindowManager(), new ActivitySwitcher.AnimationFinishedListener() {
    			@Override
    			public void onAnimationFinished() {
    				startActivity(intent);
    			}
    		});
    	}
    }

    Implement Activity2.java like Activity1.java.

    The layouts (R.layout.activity1 and R.layout.activity1) must jave a container-id like this:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    	android:id="@+id/container"
    	android:orientation="vertical"
    	android:layout_width="fill_parent"
    	android:layout_height="fill_parent">
    	<!-- ... -->
    </LinearLayout>
  4. If you want to animate an activity out when it is finished, you could override the finish() method:
    // ...
    	@Override
    	public void finish() {
    		// we need to override this to performe the animtationOut on each
    		// finish.
    		ActivitySwitcher.animationOut(findViewById(R.id.container), getWindowManager(), new ActivitySwitcher.AnimationFinishedListener() {
    			@Override
    			public void onAnimationFinished() {
    				Activity1.super.finish();
    				// disable default animation
    				overridePendingTransition(0, 0);
    			}
    		});
    	}
    // ...

That’s it! :)