Mariusz BronaAndroid Developer

Discover how to show details layout with Shared Element Transition with Scene Framework!

Welcome to the fourth and last part of my post series about the R&D (Research & Development) project, which I made a while ago. I want to share with you my solutions for problems I encountered during the development of an animation idea, shown below. In this blogpost, I will cover how to show details layout with Shared Element Transition with Scene Framework!

PRELUDE

A few months back, we had a company meeting, where my friend Paweł Szymankiewicz showed the animation he’d done during his Research & Development. And I loved it. After the meeting, I decided that I will code it. I didn’t know what I was going to struggle with…

GIF 1 “The animation”

LET’S START!

As we can see, in the GIF above, there is a lot of going on.

After clicking on the bottom menu item, we are moving to the next screen, where we can see the map being loaded with some scale/fade animation from the top, RecyclerView items are loaded with translation from the bottom, while markers are added to the map with a scale/fade animation.

While scrolling the items in RecyclerView, the markers are pulsing to show their position on the map.

After clicking on an item, we are transferred to the next screen, while the map is animated below to show the route and the start/finish marker. The RecyclerView’s item is transitioned to show some description, a bigger picture, trip details and button.

While returning, the transition happens again back to the RecyclerView’s item, showing all of the markers again, as the route disappears.

That’s pretty much it. This is also why I’ve decided to show you all of these things in a series of posts. As I have mentioned above, in this article, I will cover how to show a details layout with Shared Element Transition with Scene and Transition Framework!

THE PROBLEM

Okay, so as we can see in the GIF above, after clicking on the item in RecyclerView, we are entering the details layout with some information about our trip destination. There is definitely a Shared Element Transition, where some of the views are changing their bounds, while TextView is also changing its size and details with red buttons are sliding in from the bottom. Thanks to the Transition Framework, we are able to create this amazing animation.

My first guess was to create just like it appears in 90% of materials on the internet – via the Shared Element Transition between two Activities. However let’s look on the map. There is also an animation “underneath” the details layout – the route is being drawn and the map zooms to the fixed position. So, I guess we don’t want to create another activity with a transparent background and try to animate the map on the “background” activity.

My second guess was to create the Shared Element Transition between two fragments – add the DetailsFragment on the top of the stack and create a transition between views in both layouts – RecyclerView’s item and DetailsFragment’s layout. A better solution, but still – for me, it looks like the same screen and the same fragment, only with another layout added on top. So, do we have a solution that fits my needs?

Yes, we have! From API 19 (the Workcation App is 21 and above) we have an option – Scenes! When used with Transition Framework, they’re really powerful. We can manage our UI in a very sophisticated way. And the most important thing – it totally fits our needs! So, let’s look at the implementation!

SHARED ELEMENT TRANSITION WITH RECYCLER VIEW

Let’s start from clicking on the RecyclerView’s item. Our DetailsFragment (the one with Map and RecyclerView) implements OnPlaceClickedListener. We pass the OnPlaceClickListener interface implementation in the constructor like this:

Java

1

2

3

4

BaliPlacesAdapter(OnPlaceClickListener listener,Context context){

this.listener=listener;

this.context=context;

}

Next, in the onBindViewHolder method, we trigger the onPlaceClicked method after clicking on the RecyclerView’s item. We do this simply by passing it to onClickListener:

As you can see above, we set the onClickListener on a root element – in our case, it is a CardView. We also pass it as the first argument in the onPlaceClicked method, while the second one is fixed TransitionName – we are simply adding a position to the transition name. We do this because we have to distinguish which child of RecyclerView needs to be transitioned. If every item has the same:

Java

1

2

3

publicstaticStringgetRecyclerViewTransitionName(finalintposition){

returnDEFAULT_TRANSITION_NAME+position;

}

For the last parameter, we pass the position of the clicked item. We are using the same collection of data to fill RecyclerView item and DetailsLayout, so we just want to get the specific item by the position. Below we can see the OnPlaceClickListener and BaliViewHolder

In the first place, we save currentTransitionName as a global variable – we will need it when we will hide scene with DetailsLayout. We also assign the Scene object to the detailsScene variable – it is needed to handle the onBackPressed method properly. In the next step, we are drawing a route between our position and the destination position; parallelly, we are hiding all markers.

The part that we are mostly interested in is the one showing the scene. Let’s move to DetailsLayout.

USING SCENE FRAMEWORK TO CREATE SHARED ELEMENT TRANSITION

Below we have our custom CoordinatorLayout. It looks ordinary in the first part, but we have two additional two static methods – showScene and hideScene. Let’s look at them more closely:

In the first place, we are inflating the DetailsLayout. Next, we are setting the data (just the title and description for DetailsLayout). Next, we are creating TransitionSet – for our purpose, I’ve created a separate class to keep the codebase clean. The third step is to create the scene object – we just pass our inflated detailsLayout and containerView (the main ViewGroup of DetailsFragment – in our case, it is the FrameLayout that matches the whole screen and has RecyclerView as a child). To create our amazing animation, we just need to call one method – TransitionManager.go(scene, transitionSet). Et voila! This is our effect:

A little bit of magic happens here. TransitionManager is a class which fires transitions when the scene change occurs. With a simple call like TransitionManager.go(scene, transitionSet), we are able to go to the specific scene, where some kind of transition happens. In our case, we are showing DetailsLayout with some data about a trip destination but, when using a TransitionManager, we are able to make this kind of transition which you can see above. Now, let’s see how the ShowDetailsTransitionSet is implemented.

CREATING CUSTOM TransitionSet WITH TransitionBuiler

For keeping the code clean, I’ve created a TransitionBuilder – a simple class made using the Builder Pattern, which allows us to write less code to make a Transition, especially the Shared Element Transition. This is how it looks like:

Okay, now let’s go to the ShowDetailsTransitionSet, which creates this amazing transition. In the constructor, we pass the Context object, transitionName – this is the one that is created with the position in RecyclerView – the View object that we are transitioning from and the DetailsLayout that we are transitioning to. We also call the addTransition method, where we pass the Transition built with TransitionBuilder and returned from a specific method – textResize(), slide() and shared().

Now, there are few changes. We’ve added the DetailsLayout to DetailsFragment’s container (the FrameLayout mentioned before). So, to obtain DetailsLayout, we have to call findViewById on this container. Then, we have to create the TransitionSet with specific targets and specified settings. For this purpose, I’ve also written another class which inherits from TransitionSet – HideDetailsTransitionSet. This is how it looks:

In this case, we have textResize() and shared() transitions once again. If you look closely at both methods, you will see that this TranstionBuilder has method link(). This method takes three parameters – sourceView, targetView and transitionName. It simply puts transitionName on sourceView and targetView, as well as placing it as a target on Transition object. So it’s used to “link” two views for Shared Element Transition.

The rest looks the same. We create the Scene object, call TransitionManager.go() and voila! We have returned to the previous state!

CONCLUSION

As we can see – the sky’s the limit! We are able to create meaningful transitions with activities, fragments and even the layouts! Scenes and Transitions are really powerful and can really improve the UI and UX. What are the benefits from this solution? First of all, we don’t have another lifecycle to care about. Secondly, there are some libraries that help us to create “fragmentless” UI. Applied with Scenes and Transitions, we can develop a pretty nice app. Thirdly, this approach is really rare, however, I think it’s giving us more control.

That’s all folks! Thank you very much for reading my series of posts, I hope you liked it!