Learning new things in Android is now become more easier as compared to previous years. Especially Google and Stackoverflow covering lot of things and resources to made it easy. We at LetsNurture have been exploring upcoming technologies and have implemented in our client’s and inhouse projects. But recently we have started preparing reusable resources and libraries with the thought that it would help us to save our time and focus on the next set of problems and challenges.

Well we have implemented material design in couple of inhouse applications with awesome UI/UX and those are about to go live. Will share links later!

So from those learning and implementation, let me document and share it with the #AndroidDev community out there!

In this post

Historically, transitions between activities and fragments in Android involved animating the entire view hierarchy. With Material Design, it is now become easier to make transition between shared elements. Shared element transitions can be used to guide the user to new content and its position in the new Activity or fragment.

NOTE: You will only see this effect when running your app with a phone having Lollipop or later (SDK 21) and will be not working in any lower API versions.

Shared Element Transition
Shared Element Transition

Ok, let’s dive into the coding part.

Activity Shared Elements Transitions

1. Enable Window Content Transitions
Start of by enabling windowContentTranistion to your theme in styles.xml.

[sourcecode language=”xml”]
<!– styles.xml –>
<style name="AppTheme" …>
……..
<item name="android:windowContentTransitions">true</item>
……..
</style>
[/sourcecode]

2. Add Transition Name in View
Using android:transitionName attribute to the define shared elements, give a common transition name.

For example, android:transitionName=”userPic” which we have taken in ImageViews inside both the layouts layout_main_activity.xml and layout_target_activity.xml, yes with the common transition name as mentioned above.

layout_main_activity.xml

[sourcecode language=”xml”]

<ImageView
android:id="@+id/ivUserPic"
android:transitionName="userPic"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<TextView
android:id="@+id/tvUserName"
android:transitionName="userName"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:textSize=”12dp”
android:layout_height="wrap_content" />

[/sourcecode]

layout_target_activity.xml

[sourcecode language=”xml”]

<ImageView
android:id="@+id/ivUserPicLarge"
android:transitionName="userPic"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<TextView
android:id="@+id/tvUserNameLarge"
android:transitionName="userName"
android:scaleType="centerCrop"
android:textSize=”20dp”
android:layout_width="match_parent"
android:layout_height="wrap_content" />
…
[/sourcecode]

We apply different name as android:id to source and target view

3. Calling Activity

[sourcecode language=”java”]
Intent intent = new Intent(MainActivity.this, TargetActivity.class);
intent.putExtra(“UserInfo”, contact);
Pair<View, String> pair1= Pair.create((View)ivUserPic, "profile");
Pair<View, String> pair2 = Pair.create((View)tvUserName, "text");
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation(this, pair1, pair2);
startActivity(intent, options.toBundle());
[/sourcecode]

4. Customizing Shared Elements Transition
In Android L, shared elements transition defaults to a combination of ChangeBounds, ChangeTransform, ChangeImageTransform, and ChangeClipBounds. This works well for most typical cases. However, you may customize this behavior or even define your own custom transition.

[sourcecode language=”xml”]
<!– Base application theme. –>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!– enable window content transitions –>
<item name="android:windowContentTransitions">true</item>

<!– specify enter and exit transitions –>
<!– options are: explode, slide, fade –>
<item name="android:windowEnterTransition">@transition/change_view_transform</item>
<item name="android:windowExitTransition">@transition/change_view_transform</item>

<!– specify shared element transitions –>
<item name="android:windowSharedElementEnterTransition">
@transition/change_view_transform</item>
<item name="android:windowSharedElementExitTransition">
@transition/change_view_transform</item>
</style>
[/sourcecode]

The change_view_transform transition in this example is defined as follows:

[sourcecode language=”xml”]
<!– res/transition/change_view_transform.xml –>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<changeImageTransform/>
</transitionSet>
[/sourcecode]

To enable window content transitions at runtime instead, call the Window.requestFeature() method:

[sourcecode language=”xml”]
// inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
// set an enter transition
getWindow().setEnterTransition(new Explode());
// set an exit transition
getWindow().setExitTransition(new Explode());
[/sourcecode]

See this official guide on Defining Custom Animations for more details.

Fragment Shared Elements Transitions

Same as activities, shared element transitions works with fragments too.

Add Common Transition Name to views
Assign a common transition name to the shared elements in both Fragment’s layouts. Using android:transitionName attribute and put the view inside both MainFragment and TargetFragment like below xml file.

main_fragment.xml

[sourcecode language=”xml”]

<ImageView
android:id="@+id/ivUserPic"
android:transitionName="userPic"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<TextView
android:id="@+id/tvUserName"
android:transitionName="userName"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:textSize=”12dp”
android:layout_height="wrap_content" />

[/sourcecode]

target_fragment.xml

[sourcecode language=”xml”]

<ImageView
android:id="@+id/ivUserPicLarge"
android:transitionName="userPic"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<TextView
android:id="@+id/tvUserNameLarge"
android:transitionName="userName"
android:scaleType="centerCrop"
android:textSize=”20dp”
android:layout_width="match_parent"
android:layout_height="wrap_content" />
…
[/sourcecode]

2. Add Transition
The change_view_transform transition in this example is defined as follows:

[sourcecode language=”xml”]
<!– res/transition/change_view_transform.xml –>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<changeImageTransform/>
</transitionSet>
[/sourcecode]

3. Add Transition in FragmentTransaction
Now within the activity, we can trigger the transition as part of any FragmentTransaction:

[sourcecode language=”java”]
// Get access to or create instances to each fragment
MainFragment fragmentMain = …;
TargetFragment fragmentTarget = …;
// Check that the device is running lollipop
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Inflate transitions to apply
Transition changeTransform = TransitionInflater.from(this).
inflateTransition(R.transition.change_view_transform);
Transition explodeTransform = TransitionInflater.from(this).
inflateTransition(android.R.transition.explode);

// Setup exit transition on first fragment
fragmentMain.setSharedElementReturnTransition(changeTransform);
fragmentMain.setExitTransition(explodeTransform);

// Setup enter transition on second fragment
fragmentTarget.setSharedElementEnterTransition(changeTransform);
fragmentTarget.setEnterTransition(explodeTransform);

// Find the shared element (in FragmentMain)
ImageView ivUserPic= (ImageView) rootView.findViewById(R.id.ivUserPic);
TextView tvUserName=(TextView) rootView.findViewById(R.id.tvUserName);

// Add second fragment by replacing first
FragmentTransaction ft = getFragmentManager().beginTransaction()
.replace(R.id.container, fragmentTarget)
.addToBackStack("transaction")
.addSharedElement(ivUserPic, "userPic")
.addSharedElement(tvUserName, "userName");
// Apply the transaction
ft.commit();
}
else {
// Code to run on older devices
}
[/sourcecode]

Download Example Project

You can download the example project to check how it works. Download from https://github.com/pranaypatel512/SharedElementTransitions

References

Wrapping up

That’s it for this part. I hope to explore more such features and functionalities of material design! I am sure this is enough for those who wants to learn and implement shared elements transition, in case if you implement it or have already implemented it, please feel free to share an app or links in comments.

Pranay Patel

Software Engineer at @LetsNurture || #AndroidDev #twitter || @SOreadytohelp #github #java #database #security #ethicalhacking || #TEA

Want to work with us? We're hiring!