Before Android 5.0 Lollipop animations between activities weren't a strong point of Android apps. There weren't many ways to create a smooth and engaging experience for the user. A lot of apps looked the same when it comes to activity transitions. Fortunately Android 5.0 brought new Transitions API. It gives lots of new possibilities, not only activity transitions, but in this article I will focus on that area. Keep in mind, that Google doesn't provide backport library and there is no chance to do it on lower versions of Android.

Let's start!

How to implement good looking animation in the fastest way? Follow me!

Let's assume that we have activity with a grid of images from phone memory. How to grab it you can see in the sample app repository. Mentioned activity can be named "MainActivity". Once you click on the image, app opens new activity, let's say "DetailActivity". What will be fancy in this usual behavior? Cool animation! Image thumbnail from grid starts to increase it's bounds and move to the center of the screen. Old activity will be replaced by new activity at the same time. After pressing the return button, all the things will change in reverse order.

Let’s code!

Activities should extend AppCompatActivity class as you can see in example app.

In layout resource file remember to name transition:

item_view.xml

<ImageView
    android:id="@+id/image"
    android:transitionName="@string/image_transition"
    android:adjustViewBounds="true"
    android:scaleType="centerCrop"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

You also can do this programmatically:

view.setTransitionName(context.getString(R.string.image_transition));

but it causes app crash, when you install and use it on lower than Lollipop versions of Android. Using „android:transitionName” in xml file is safe, because unrecognized properties will be skipped.

Next, you should do the same in layout resource file that we want to show in detail activity:

activity_detail.xml

<ImageView
    android:id="@+id/image"
    android:transitionName="@string/image_transition"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scaleType="centerInside" />

It is very important to use the same name for the pair of views, which we want to animate.

The last step is open the activity in new way:

RecyclerViewAdapter.java

ActivityOptionsCompat options = ActivityOptionsCompat
        .makeSceneTransitionAnimation(context,
                                    holder.image, 
                                    context.getString(R.string.image_transition));
Intent intent = new Intent(context, DetailActivity.class);
context.startActivity(intent, options.toBundle()).

That’s all! Effect of this several lines of code you can see below:

Animation 1

What to do if you want to share two or more view pairs between activities?

Associate views by creating pairs!

RecyclerViewAdapter.java

Pair<View, String> p1 = Pair.create((View)holder.image, 
                                    holder.image, 
                                    context.getString(R.string.image_transition));
Pair<View, String> p2 = Pair.create((View)holder.imageName, 
                                    holder.image, 
                                    context.getString(R.string.name_transition));

Intent intent = new Intent(context, DetailActivity.class);
ActivityOptionsCompat options = ActivityOptionsCompat
                                        .makeSceneTransitionAnimation(context, p1, p2);
context.startActivity(intent, options.toBundle());

Simple, quick and amazing:

Effect of this several lines of code you can see below:

Animation 2

Notice, that Lollipop API provides View.getTransitionName() method. So you don’t need get string resource as in example. Why did I implement it that way? Compatibility with lower versions of Android! Using ActivityOptionsCompat causes opening new activity with transition animation on Android >= 5.0 and in the old way (without animation) on lower versions without any additional lines of code. You can see it below. So you can support old Android devices without effort. Google, why so few APIs work this way?

Animation 3

How to do a reverse animation?

You have to write 0 lines of code :) Transition API does it for you automagically.

What if you want to do something special with your image?

It can be basically resizing, because ImageView can load an image of maximum size 4096x4096. Just put this line:

postponeEnterTransition();

in onCreate method and this line:

startPostponedEnterTransition();

when you are ready to open new activity. It is very useful, when image is loading from url, for example by Picasso:

Picasso.with(MainActivity.this)
        .load(imageUrl)
        .into(imageView, new com.squareup.picasso.Callback() {
                    @Override
                    public void onSuccess() {
                        startPostponedEnterTransition();
                    }

                    @Override
                    public void onError() {
                        //do something when there is image loading error
                    }
                });

Of course, you should show loader or something like this, because Activity will be waiting with opening to time, when image will be downloaded. User might be very saddened by this fact.

Do you like explosions?

This is a part specially for you and other animation enthusiasts ;) Below is a very simple example how to implement zappy transition between activities. When app open new activity, the previous activity disappears in a nice way:

MainActivity.java

Transition transition = new Fade();
    transition.setDuration(600);
    transition.setInterpolator(new FastOutLinearInInterpolator());
    getWindow().setExitTransition(transition);

And when app pops mentioned new activity, we will see explosion:

MainActivity.java

Transition transition = new Explode();
    transition.setDuration(600);
    transition.setInterpolator(new FastOutLinearInInterpolator());
    getWindow().setReenterTransition(transition);

See, how it looks:

Animation 4

Apart from this, Transition API offers also Slide animation. Unfortunately, app will crash on Android < 5.0, so it is necessary to check Android SDK version, when support old versions is required.

Do you want to know how it is work under the hood?

Read this article: http://www.androiddesignpatterns.com/2015/01/activity-fragment-shared-element-transitions-in-depth-part3a.html

Sample app repository:

https://github.com/sekdariusz/BTGallery

About the author:

Dariusz Sęk

Android and iOS Developer in BT Skyrise. After work, Darek plays with his chow chow or uses it for manual debugging code. This is a new method having roots in „Rubber duck debugging” and it is practiced only in Poland.

Next Post Previous Post

blog comments powered by Disqus