Understanding Shared Element Transition in Android.

By | December 27, 2016

Hi all,

In Today’s tutorial we will see how we can do a shared element transition between activities in android.

What we will do.

  • We have two activities
  • First activity has a TextView and two images.
  • Second activity with two images.
  • We will animation between corresponding images.

Check out the video below to see what we are going to do

Transitions to corresponding element is done by using the “transitionName” property mentioned in the views.

Lets look at the first activity layout

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:onClick="onClick"
    android:orientation="vertical"
    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="demo1.coderzheaven.com.animationdemo1.MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:layout_gravity="center"
        android:id="@+id/tv"
        android:text="Add a new Button with default transition" />

    <LinearLayout
        android:id="@+id/l1"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </LinearLayout>

    <ImageView
        android:id="@+id/sharedimage1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:transitionName="android_shared_1"
        android:src="@drawable/and1" />

    <ImageView
        android:id="@+id/sharedimage2"
        android:layout_weight="1"
        android:src="@drawable/and2"
        android:transitionName="android_shared_2"
        android:scaleType="centerCrop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

activity_second.xml


<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:background="@color/colorAccent"
    tools:context="demo1.coderzheaven.com.animationdemo1.SecondActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <RelativeLayout
        android:id="@+id/content_second"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/sharedimage1"
            android:layout_alignParentTop="true"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:transitionName="android_shared_1"
            android:src="@drawable/and1" />

        <ImageView
            android:id="@+id/sharedimage2"
            android:src="@drawable/and2"
            android:layout_alignParentTop="true"
            android:transitionName="android_shared_2"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </RelativeLayout>

</android.support.design.widget.CoordinatorLayout>


Note that the two imageviews for which we want the transition will have same “android:transitionName” value.

for eg : android:transitionName=”android_shared_1″.

For all these animations to happen we need to specify transiton item in the XML or in java code for styles.

In XML

<item name="android:windowContentTransitions">true</item>

In Java

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

MainActivity.java


import android.animation.LayoutTransition;
import android.app.ActivityOptions;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        setContentView(R.layout.activity_main);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // Simple Layout animation
            LayoutTransition l = new LayoutTransition();
            l.enableTransitionType(LayoutTransition.CHANGING);
            ((ViewGroup) findViewById(R.id.l1)).setLayoutTransition(l);
        }

        findViewById(R.id.tv).setOnClickListener(this);
        findViewById(R.id.sharedimage1).setOnClickListener(this);
        findViewById(R.id.sharedimage2).setOnClickListener(this);
    }

    private void startNewActivityWithSharedTransition(View sharedImage) {
        Intent intent = new Intent(MainActivity.this, SecondActivity.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            ActivityOptions options =
                    ActivityOptions.
                            makeSceneTransitionAnimation(MainActivity.this, sharedImage, sharedImage.getTransitionName());
            intent.putExtra("TransName", sharedImage.getTransitionName());
            startActivity(intent, options.toBundle());
        } else {
            startActivity(intent);
        }
    }

    @Override
    public void onClick(View view) {

        if (view instanceof TextView) {
            if (((ViewGroup) findViewById(R.id.l1)).getChildCount() == 2)
                ((ViewGroup) findViewById(R.id.l1)).removeAllViews();
            ((ViewGroup) findViewById(R.id.l1)).addView(new Button(this));
        } else {
            startNewActivityWithSharedTransition(view);
        }
    }

}

SecondActivity.java


import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.ImageView;

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        Bundle b = getIntent().getExtras();
        if (null != b) {
            String transName = getIntent().getExtras().getString("TransName");
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                ImageView sharedImg1 = (ImageView) findViewById(R.id.sharedimage1);
                sharedImg1.setVisibility((transName.contentEquals(sharedImg1.getTransitionName()) ? View.VISIBLE : View.GONE));
                ImageView sharedImg2 = (ImageView) findViewById(R.id.sharedimage2);
                sharedImg2.setVisibility((transName.contentEquals(sharedImg2.getTransitionName()) ? View.VISIBLE : View.GONE));
            }
        }
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        supportFinishAfterTransition();
    }
}

Now for reversing the transition you need to call “supportFinishAfterTransition()” instead of “finish” in the closing Activity.

Leave a Reply

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