Implementing the Motion System With Material Components for Android
A Deep Dive Into the Motion Transition With the new Update of the Material Design Component Library
Google recently released an alpha update(1.2.0-alpha05) of its material components library that includes the implementation of The motion system which is a set of guidance for transition patterns between views.
The motion system categories transition pattern of views and fragments/activities in 4 different types
Container transform
The container transform pattern is used when the transition includes a persistent container (buttons, lists, or cards) that transitions into a detailed view.
Note: It’s a shared element transition but unlike the traditional shared element transition that works on a single shared element between both views container transformation changes the bounds of start view to the bounds of end view which can be two different views on the same screen or a view on different fragment/activity.
Container transformation between two fragments
Container transformation is a shared element transition so first, we need to assign the transition name to both containers. In the first layout, it can be anything like a card, list item, or a button. As shared element transition works on 1:1 mapping so we need to provide a unique transition name to each list item if we are working with lists. There is a great article about shared element mapping here.
In our example, we have a list of all the Eminem albums in recycler view so first, we assign the transition name to each item inside the adapter holder itemBinding.root.transitionName = album.name
. We are just setting a unique transition name to each row’s root item layout.
Now when we select an album we need to tell the end container about the item’s transition name and the shared view. We have SafeArgs and FragmentNavigator class which helps us in passing the bundle and shared view.
We are using the SafeArgs gradle plugin to pass the selected album and transition name to the album detail page. FragmentNavigatorExtras
class takes Pair<View, String>
as input. So we pass the shared view and transition name to it. All the internal work is done by Navigation Component.
Check out this nice tutorial for more information on how to do a shared element transition with the navigation component on official developer docs.
To set the Shared Element Transition to the album detail screen we create an object of MaterialContainerTransform
inside OnCreate()
and set it to sharedElementEnterTransition
We also have to set the transition name to the container of album detail
We have plenty of options to customize our container transformation like fadeMode
, scrimColor
, fitMode
, pathMotion
, etc.
Note: Currently there is an issue with sharedElementReturnTransition
. The container doesn’t shrink its bound when pressed back.
Container transformation between two views
We can use container transformation to transform one view to another by setting our startView
and endView
in the same layout and changing their visibility with TransitionManager.beginDelayedTransition
.
This will perform a container transform between the start view transitioning to the end view and if want to reverse the transition all we have to do is flip the startView
& endView
and change visibility accordingly.
Shared axis
This pattern is best to use when views have a navigation relationship between them. for e.g, clicking on the next and previous buttons move the screens.
Shared axis work on three axis X, Y, and Z.
We can use this transition by creating an instance of MaterialSharedAxis
class passing context, axis, and a boolean telling if this is a forward transition or backward transition. Passing true
will make it a forward transition and backward if we pass false
.
In the X-axis transition, a forward transition means views will transition to the left of the X-axis and the backward means transition to the right of the X-axis. outgoing views will fade out and slide out 30dp horizontally and the incoming view will fade in and slide in 30dp.
in the Y-axis transition, a forward transition means a transition in the upper direction, and backward means a transition in the bottom direction. outgoing views will fade out and move out 30dp vertically and incoming views will fade in and move in 30dp vertically.
in the Z-axis transition, outgoing views will fade out and scale from 100% to 110%, and incoming views will fade in and scale from 80% to 100%.
Shared axis transformation between two fragments
We set exitTransition
on the first fragment and enterTransition
on the second fragment to forward because want these fragments to move to the left when exiting and entering at the same time.
reenterTranstion
and returnTransition
to backward because we want them to move right so it feels like the first fragment is coming from the back stack and the second fragment is moving back to where it came from.
Note: Currently there seems to be an issue with MaterialSharedAxis
. Transition is not as smooth as they show in the example and by default secondaryTransition
doesn’t work on outgoing views.
Shared axis transformation between two views
Above gives us a nice X-axis transition between the two images.
Fade through
This pattern should be used when there is no strong relation between transitioning UI elements for eg. taping the bottom app bar item should trigger the Fade through transition between incoming and outgoing fragments.
We use MaterialFadeThrough
class to achieve this transformation between views. This class has two transitions, a primaryTransition
which is a FadeThrough transition and a secondaryTransition
which is a scale transition. Both transitions extend the Visibility class so MaterialFadeThrough
animates views depending on whether they are appearing or disappearing from the scene.
- Fade through between fragments
The above example will give the effect of fade-in and scale up if the fragment is entering or fade-out and scale down if the fragment is exiting the screen.
- Fade through between two views
We can also use MaterialFadeThrough
to transform two views with some help from TransitionManager
class.
Fade
The fade pattern is used for views that enter or exit within the screen. e.g showing/hiding the dialogue or floating action button.
We can use MaterialFade
class to create a simple fade animation. This class also has two transitions primaryTransition
and secondaryTransition
like MaterialFadeThrough
which extends Visibility
class which means view’s visibility should be changed in order to trigger this transition.
In the above example, we simply change our play button visibility so it fades in and scales up after 1 second.
Both MaterialFadeThrough
& MaterialFade
extends MaterialTransitionSet
which means we can modify the secondaryTransition
to our own transition which extends Visibility
class or we can completely remove the secondaryTransition
just by setting it to null.
The Motion System guidelines are in beta so they can change in the future. Also, the motion system library is in its alpha stage so there are some bugs that will be solved in upcoming releases (hopefully).
Thanks for reading. I’d love to hear from you in the comments.