22 December 2014

Android Lollipop Shared Elements


In Lollipop the new material design has given us a new feature called shared elements or shared transitions. This allows us an easy method of animating common elements between screens. Sure it doesn't add any features, but it looks nice. Anything that gives the user a tiny bit of a happy design feeling is worth some effort.

The kodaline example demonstrates this:
http://android-developers.blogspot.co.uk/2014/10/implementing-material-design-in-your.html

It wasn't immediately obvious to me how this works after following Android developer's code examples there. So I created a simple example. I wasn't really interested in the full page animation with all the other pieces animating into place. I just wanted a really quick and easy win to take advantage of material. My example is a main activity with two small images on. Then a details activity with a single large activity. You click on an image, it gets bigger.

So there are four elements to this simple transition.


  1. values-v21/styles.xml
    Create a values-v21 directory in your res folder and add in a styles.xml file. This will override your existing styles file for Lollipop, you need the windowContentTransitions element. Here's my whole file:

    <?xml version="1.0" encoding="utf-8"?>
    <resources xmlns:android="http://schemas.android.com/apk/res/android">
    
        <style name="AppTheme" parent="android:Theme.Material">
            <item name="android:windowContentTransitions">true</item>
        </style>
    </resources>
    


  2. Activity xml
    Add a transitionName element to the xml of the item you wish to share. For my example I'm just using an image, so I've added the transitionName  to the image in activity_main, and of course the image in the details activity.

    Activity main:
        <ImageView
            android:id="@+id/activity_main_monkey"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_gravity="center_horizontal"
            android:tag="@string/monkey"
            android:layout_marginTop="30dp"
            android:transitionName="@string/MyTransitionName"
            android:src="@drawable/monkey" />
    

    Activity Details:
        <ImageView
            android:id="@+id/activity_details_image"
            android:layout_width="wrap_content"
            android:layout_height="400dp"
            android:layout_gravity="top|center_horizontal"
            android:layout_marginTop="10dp"
            android:transitionName="@string/MyTransitionName"
            android:src="@drawable/monkey" />
    


  3. Launch detail activity from main
    Now comes the bit where we launch the second activity, from the first. Normally this is just a simple startActivity but the magic of shared transitions works by adding some options here. The important bit is this:
    options = ActivityOptions.makeSceneTransitionAnimation(this, v, getString(R.string.MyTransitionName));
    

    As you can see we use the same transition name we put in the xml. I've also added in a few if statements so we can run this on pre lollipop and it won't crash.

        @SuppressLint("NewApi")
        private void startDetailsActivity(View v){
            Intent intent = new Intent(this, DetailsActivity.class);
            ActivityOptions options = null;
            // create the transition animation - the images in the layouts of both activities are defined with android:transitionName="MyTransition"
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.L) {
                options = ActivityOptions.makeSceneTransitionAnimation(this, v, getString(R.string.MyTransitionName));
            }
            intent.putExtra(DetailsActivity.TAG_IMAGE_NAME, (String) v.getTag());
            // start the new activity
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && options != null) {
                this.startActivity(intent, options.toBundle());
            }else{
                startActivity(intent);
            }
        }
    
That's it. Hope it helps.

Here's the code: https://github.com/jimbo1299/shared-transitions



05 December 2014

Lollipop update for Nexus 7 (2012) - Update


I previously blogged about problems with Lollipop on my Nexus 7. After quite a few emails with Google Play support I have been promised that an update to fix this issue began roll out globally on 3rd December. So fingers crossed the many upset users out there will shortly have the problem solved. Well done Google (assuming it works).