Introduction
The Android transitions framework allows you to configure the appearance of changes in your app's user interface. You can animate changes in an app screen, defining each phase as a scene and controlling the way in which the transition changes the app appearance from one scene to another.
In this tutorial, we will build a simple app with an animated transition in it. This will involve preparing the layout and drawable files in XML, then configuring and applying the transition in Java. We will define two scenes in which the same view items are arranged differently on the screen. As we use a transition, Android will automatically animate the change from one scene to another.
1. Create the App
Step 1
Start by creating a new app in your chosen IDE. You need a minimum SDK of 19 for the transitions classes, so you'll need to take additional steps if you plan on supporting older versions.
Give the app a main Activity
and layout file, choosing the name start_layout.xml for the layout. We will be adding another layout file later, using the transition to change from one to the other. The following images show the process in Android Studio.
Step 2
Let's now prepare some drawable shapes to use in the transition. We will use four circle shapes with different colored gradient fills. In your app's drawables resource directory, start by creating a new file named shape1.xml. Enter the following shape:
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:dither="true" android:shape="oval" ><gradient android:endColor="#66ff0000" android:gradientRadius="150" android:startColor="#ffffcc00" android:type="radial" android:useLevel="false" /><size android:height="100dp" android:width="100dp" /></shape>
The shape is a circle with a radial gradient fill. All four of the shapes will be the same except for the colors used within them. You may wish to create different versions of the drawables for different device densities. Add shape2.xml next:
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:dither="true" android:shape="oval" ><gradient android:endColor="#66ffcc00" android:gradientRadius="150" android:startColor="#ff00ff00" android:type="radial" android:useLevel="false" /><size android:height="100dp" android:width="100dp" /></shape>
Now add shape3.xml:
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:dither="true" android:shape="oval" ><gradient android:endColor="#6600ff00" android:gradientRadius="150" android:startColor="#ff0000ff" android:type="radial" android:useLevel="false" /><size android:height="100dp" android:width="100dp" /></shape>
Finally add shape4.xml:
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:dither="true" android:shape="oval" ><gradient android:endColor="#660000ff" android:gradientRadius="150" android:startColor="#ffff0000" android:type="radial" android:useLevel="false" /><size android:height="100dp" android:width="100dp" /></shape>
We will use these shapes as ImageButtons
in the two layout scenes.
2. Create the Layout Scenes
Step 1
Let's define the two scenes we will transition between as XML layouts. Start with the main layout file you added when you created the app, start_layout.xml. Open it and switch to the XML editing tab. Use a RelativeLayout
as shown below:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ff000000" android:id="@+id/base" tools:context=".TransitionsActivity"></RelativeLayout>
We add a background color and ID for the layout. The ID is essential to ensure that Android transitions between your scenes, we will be using the same ID in the second scene. When you transition between two scenes, Android will animate the changes as long as each view has the same ID in both scenes, otherwise it will treat the views as different and simply fade them in or out when the transition occurs.
Inside the RelativeLayout
, add an ImageButton
for each shape we created:
<ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn1" android:src="@drawable/shape1" android:background="#00000000" android:contentDescription="shape" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:onClick="changeScene"/><ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn2" android:src="@drawable/shape2" android:background="#00000000" android:contentDescription="shape" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:onClick="changeScene"/><ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn3" android:src="@drawable/shape3" android:background="#00000000" android:contentDescription="shape" android:layout_alignParentLeft="true" android:layout_alignParentBottom="true" android:onClick="changeScene"/><ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn4" android:src="@drawable/shape4" android:background="#00000000" android:contentDescription="shape" android:layout_alignParentRight="true" android:layout_alignParentBottom="true" android:onClick="changeScene"/>
Notice that each shape button has an ID, which will be the same in the second layout we create, and an onClick
attribute. We will include this method in the main Activity
later and will start the transition when the user clicks any of the shapes.
You will see a preview of the layout in your IDE, although in some cases the gradient and/or transparency will not be displayed until you actually run the app on a device or the emulator. The shapes are arranged to sit in each corner of the screen as shown below.
Step 2
The first layout we created will represent the start of the transition. Let's now create a second layout file for the scene the transition will change to. Add a new file in your app layout resources directory, naming it end_layout.xml. Switch to the text editing tab and enter the following:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ff000000" android:id="@+id/base" tools:context=".TransitionsActivity"><ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn1" android:src="@drawable/shape1" android:background="#00000000" android:contentDescription="shape" android:layout_alignParentRight="true" android:layout_alignParentBottom="true" android:onClick="changeScene"/><ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn2" android:src="@drawable/shape2" android:background="#00000000" android:contentDescription="shape" android:layout_alignParentLeft="true" android:layout_alignParentBottom="true" android:onClick="changeScene"/><ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn3" android:src="@drawable/shape3" android:background="#00000000" android:contentDescription="shape" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:onClick="changeScene"/><ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn4" android:src="@drawable/shape4" android:background="#00000000" android:contentDescription="shape" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:onClick="changeScene"/></RelativeLayout>
Take a moment to look at the layout code. It is identical to the first layout except for the positions of the shape buttons. Each shape is in the opposite corner from its position in the first layout. The transition will therefore swap the shapes, moving their positions diagonally across the screen.
3. Transition Between Scenes
Step 1
We have the two layouts defined, let's now use a transition to move between them. Open your app's main Activity
class. You will need the following import statements:
import android.transition.AutoTransition; import android.transition.Scene; import android.transition.Transition; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateDecelerateInterpolator; import android.widget.RelativeLayout; import android.transition.TransitionManager;
Inside the Activity
class declaration, before the onCreate
method, add the following instance variables we will use to apply the transition:
//scenes to transition private Scene scene1, scene2; //transition to move between scenes private Transition transition; //flag to swap between scenes private boolean start;
Step 2
Now let's prepare for the transition, which will begin when the user clicks a shape. In onCreate
, after the existing code your IDE has entered, add the following:
//get the layout ID RelativeLayout baseLayout = (RelativeLayout)findViewById(R.id.base); //first scene ViewGroup startViews = (ViewGroup)getLayoutInflater() .inflate(R.layout.start_layout, baseLayout, false); //second scene ViewGroup endViews = (ViewGroup)getLayoutInflater() .inflate(R.layout.end_layout, baseLayout, false);
First we define the base scene, which is the ID we gave the containing layout in both scene layout files. Next we define the two scenes we are transitioning between, specifying their layout file names and the containing base scene. This will tell Android we want to transition the views within the two scenes, treating any view with the same ID in both scenes as the same object, so that it animates the change from one scene to the other.
Next, we define the two scenes we want to transition between, still in onCreate
:
//create the two scenes scene1 = new Scene(baseLayout, startViews); scene2 = new Scene(baseLayout, endViews);
We pass the base layout and relevant scene layouts to each constructor. Now we can refer to these scenes when defining the transition.
Step 3
Let's get the transition prepared, still in onCreate
:
//create transition, set properties transition = new AutoTransition(); transition.setDuration(5000); transition.setInterpolator(new AccelerateDecelerateInterpolator()); //initialize flag start=true;
Android provides a range of transition types depending on how you want the changes in your scenes to be animated. In this case, we choose an AutoTransition
, so Android will calculate how to make the change based on the properties that are altered between scenes. See the Transitions reference for more options.
We set a duration and interpolator for the transition. You can optionally also set a start delay for the change. Finally, we initialize the boolean flag to true. For simplicity we will use this to swap between the two scenes whenever the user clicks a shape, but this is just to demonstrate the functionality involved.
Step 4
Remember that we added an onClick
attribute to the shape buttons when we created the layout XML. Let's add that method to the Activity
now:
public void changeScene(View v){ //check flag if(start) { TransitionManager.go(scene2, transition); start=false; } else { TransitionManager.go(scene1, transition); start=true; } }
We use the TransitionManager
to transition from the current scene to the other scene, with the boolean flag keeping track of which one we are on. We specify the Transition
object we created to tailor how the change unfolds.
You should now be able to run your app and see the transition whenever you click a shape. Each time you click, the transition should move the shapes slowly to the opposite corners, then swap them back when you click again.
Conclusion
In this tutorial we have really only begun to explore what you can do with the Android transitions framework. To develop your transitions further, check out the additional methods in the TransitionManager
class, such as beginDelayedTransition
and transitionTo
. You can also use a TransitionSet
to combine multiple transitions, for example, to configure fading and moving effects. Depending on the complexity of your transitions, you may also benefit from the TransitionValues
class, which provides a reference to data values relevant to the transition. For more on what you can do with scenes, check out the Scene
class as well.