An Introduction to Android Transitions

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.

Advertisement
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.

Comments

Popular posts from this blog

How to Create a Yoga Goddess Illustration in Adobe Illustrator

How to Create an Icon Set using Adobe Photoshop

Android Essentials: Using the Contact Picker