Android Transitions: A Practical Example

In this series of posts I will develop a more practical example to show where transitions can be useful. In this post I will start with the initial layout and design of a user interface and create the default transitions between them. The example will revolve around an input form in which the user is able to enter different types of information depending on the choice.

Imagine an application that allows the user to store notes of different kinds. A note could contain a link to a web site, an image, an event or a contact. I will not be developing an application to store, share or sync these notes. I will only focus on the input form of this hypothetical note keeping application. The complete project can be found on github.

To start I design the layout of the input form. For this small example, a I will start from a rough sketch of the layout. The form will consist of four icons at the top representing the four types of data that the user might want to store. The user can select the type of data by clicking on one of the four icons. Below the icons is the actual input form. The layout will depend on the selection of the user and it will contain different types of data in each case.

The Resources

For the icons, I use the action bar icon pack from the Android design resources site. I will use the following icons: ic_action_web_site.png for the web site icon, ic_action_picture.png for the image icon, ic_action_person.png for the contact icon and ic_action_event.png for the event icon. These icons are copied into the res/drawable-*** folders for their respective resolutions.

In addition I will need each of the icons with a coloured overlay to be used when the corresponding icon is selected. For this I create new drawable resources. The drawable resource for the web site icon is stored in action_web_site_selected.xml inside the /res/drawable folder.

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
  <item android:drawable="@drawable/ic_action_web_site" />
  <item>
    <shape android:shape="rectangle">
      <gradient android:startColor="@color/transparent_blue"
        android:endColor="@color/less_transparent_blue"
        android:angle="-90"/>
    </shape>
  </item>
</layer-list>

The drawable contains the icon for the web site and, on top of that, a vertical colour gradient that starts with a transparent blue and ends with a slightly less transparent blue. A similar file is created for the other three icons. In order to make this work I define the two colours in the colours.xml file in the res/values directory.

<color name="transparent_blue">#4033B5E5</color>
<color name="less_transparent_blue">#8033B5E5</color>

The values for the colours are taken from the colour swatches on the Android design resources site.

The Basic Layout

I start with the basic layout. I will explain in detail the layout for the input for for the web site link. The input forms for the other types of data follow a similar pattern and I will only touch on them. At the top of the input form we will display the four icons. The icon representing the web site will be highlighted. I will use a linear layout to achieve an even spacing between the icons.

<LinearLayout
  android:id="@+id/choice_bar"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_marginTop="8dp"
  android:orientation="horizontal" >

  <ImageView
    android:id="@+id/link_icon"
    android:layout_width="0dp"
    android:layout_height="48dp"
    android:scaleType="fitCenter"
    android:layout_weight="1"
    android:src="@drawable/action_web_site_selected" />
  <ImageView
    android:id="@+id/image_icon"
    android:layout_width="0dp"
    android:layout_height="48dp"
    android:scaleType="fitCenter"
    android:layout_weight="1"
    android:src="@drawable/ic_action_picture"
    android:onClick="showPictureForm" />
  <ImageView
    android:id="@+id/contact_icon"
    android:layout_width="0dp"
    android:layout_height="48dp"
    android:scaleType="fitCenter"
    android:layout_weight="1"
    android:src="@drawable/ic_action_person"
    android:onClick="showContactForm" />
  <ImageView
    android:id="@+id/event_icon"
    android:layout_width="0dp"
    android:layout_height="48dp"
    android:scaleType="fitCenter"
    android:layout_weight="1"
    android:src="@drawable/ic_action_event"
    android:onClick="showEventForm" />
</LinearLayout>

I use ImageView for the icons and set the scale type to fitCenter. This ensures that the height of the icons is fixed to 48dp and the icons are not stretched horizontally. The web site icon uses the drawable that includes the blue gradient, defined earlier. All the other icons use references to the pngs. Also note that the onClick property is set for the three icons that are not selected. They are linked to methods in the activity that I will define later.

The linear layout is placed inside a merge element, together with the rest of the form layout.

<merge xmlns:android="http://schemas.android.com/apk/res/android" >

  <LinearLayout> <!-- as above --> </LinearLayout>

  <View
    android:id="@+id/top_divider"
    android:layout_width="fill_parent"
    android:layout_height="1px"
    android:layout_below="@+id/choice_bar"
    android:layout_margin="8dp"
    android:background="@color/light_gray" />

  <TextView
    android:id="@+id/header_label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_below="@id/top_divider"
    android:layout_margin="8dp"
    android:labelFor="@+id/header"
    android:text="@string/label_title"
    android:textSize="24sp" />

  <EditText
    android:id="@+id/header"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_alignBaseline="@id/header_label"
    android:layout_alignParentRight="true"
    android:layout_margin="8dp"
    android:layout_toRightOf="@id/header_label"
    android:inputType="text"
    android:textSize="24sp" >

      <requestFocus />
    </EditText>

  <TextView
    android:id="@+id/link_label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_below="@id/header_label"
    android:layout_margin="8dp"
    android:labelFor="@+id/link"
    android:text="@string/label_link"
    android:textSize="24sp" />

  <EditText
    android:id="@+id/link"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_alignBaseline="@id/link_label"
    android:layout_alignParentRight="true"
    android:layout_margin="8dp"
    android:layout_toRightOf="@id/link_label"
    android:inputType="text"
    android:textSize="24sp" />

  <TextView
    android:id="@+id/comment_label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/link_label"
    android:layout_margin="8dp"
    android:labelFor="@+id/comment"
    android:text="@string/label_comment"
    android:textSize="24sp" />

  <EditText
    android:id="@+id/comment"
    android:layout_width="match_parent"
    android:layout_height="54dp"
    android:layout_marginLeft="8dp"
    android:layout_marginRight="8dp"
    android:layout_marginBottom="8dp"
    android:layout_below="@id/comment_label"
    android:inputType="textMultiLine"
    android:textSize="18sp" />

</merge>
Layout for the scene containing the input form for a web link.

Layout for the scene containing the input form for a web link.

The form contains one input field for the title, one for the URL and one for a comment that the user might want to add. A screenshot of the finished input form can be seen on the right.

I will not paste the code of the other layouts here. They follow pretty much the same pattern. You can find the layouts on github. One thing to note is that input elements and labels that serve the same purpose in each form have the same ids. In this way the transition system knows which views to pair up and create animations for the transition.

To keep it simple, the main layout for the activity is a RelativeLayout contained inside a basic FrameLayout.

<FrameLayout 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="@android:color/background_light"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  tools:context=".MainActivity" >

  <RelativeLayout
    android:id="@+id/main_container"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:padding="8dp"
    android:background="@android:drawable/dialog_holo_light_frame" >

    <include layout="@layout/scene_link" />
  </RelativeLayout>

</FrameLayout>

Note that I have included the first scene in the layout using the include tag. In the introduction to the transition system I have shown how to initialise the initial scene programmatically. Using the include tag is an alternative to the programmatic initialisation and might be your preferred choice if the fist scene is always known.

The Main Activity

The main activity has to initialise the four scenes and keep a reference to the view group in the main layout that contains the scenes. This is done in the onCreate method.

  ViewGroup container;
  Scene webSiteForm;
  Scene pictureForm;
  Scene contactForm;
  Scene eventForm;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);

    container = (ViewGroup) findViewById(R.id.main_container);
    webSiteForm = Scene.getSceneForLayout(container, R.layout.scene_link, this);
    pictureForm = Scene.getSceneForLayout(container, R.layout.scene_picture, this);
    contactForm = Scene.getSceneForLayout(container, R.layout.scene_contact, this);
    eventForm = Scene.getSceneForLayout(container, R.layout.scene_event, this);
  }

Now all that is left to do is invoke the transitions when the icons in the top row are clicked. I have already set the onClick property of the ImageViews. The implementation of the methods in the main activity is straightforward.

  public void showWebSiteForm(View view) {
    TransitionManager.go(webSiteForm);
  }

  public void showPictureForm(View view) {
    TransitionManager.go(pictureForm);
  }

  public void showContactForm(View view) {
    TransitionManager.go(contactForm);
  }

  public void showEventForm(View view) {
    TransitionManager.go(eventForm);
  }

As discussed in the Introduction to Transitions, the static method TransitionsManager.go replaces the contents of the view group with the contents of the scene. The manager chooses the default transition for the scene change. We will customise the transitions in the next instalment of this series.

Follow the author

3 Comments

  1. bluebaniya.com

    very good article…useful for us

    bluebaniya.com

    Reply
  2. santhiya.R

    Excellant post!!! very very usefull for me

    Reply
  3. Anbarasu

    very useful article…

    Reply

Leave a Comment

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>