[MUSIC PLAYING]
NICK ROUT: Hi.
Welcome to the final episode in our Material Design Components
series.
Following on from our episodes on material theming
and dark theme, today we're going
to be exploring Material Motion system.
Material Motion distills common transitions
into a group of simple patterns for a smoother, more
understandable user experience.
The four patterns are container transform, shared axis,
fade through, and fade.
These are implemented in MDC as classes
built on top of the existing AndroidX and platform
transition frameworks.
As a result, they can be used in scenarios involving fragments--
including the navigation component-- activities, views,
and windows.
We'll be exploring each of these transition patterns,
and in which scenarios they are best
suited, by applying them to a sample app.
We'll also see how adjusting animation values
such as duration and interpolaters
can change the user experience.
For this episode, we're going to be using
an existing app called Reply.
This is one of the material studies, an email app that
uses material design components and material theming
to create an onbrand communication experience.
Visit material.io/design/studies/reply
for more information.
We are now in the Material Components Android Examples
repository.
It includes Reply as well as other sample apps
that demonstrate MDC, like Owl and MaterialThemeBuilder.
There's also the Material Components Android Motion
Codelab repo, which also uses Reply and runs
through the same steps as this video in Codelab form.
We'll need to clone it to our machine.
We can then open an existing project
in Android Studio using the root directory.
We are now set up with the Reply project,
and have the app running on an emulator.
Reply is a great example of material theming, dark theme,
and effective use of MDC widgets.
It has a main activity and multiple fragments as screens--
Home fragments, Email fragments, Compose fragments, and more--
and moves between them using the navigation components.
However, it currently doesn't include any transitions
between nav destinations.
So let's fix that.
Let's begin by adding a transition
when clicking on an email.
For this navigation change, the Container Transform pattern
is well suited, as it's designed for transitions
between UI elements that include a container.
This pattern creates a visible connection
between two UI elements.
A container transform in the MDC library
is called a MaterialContainerTransform.
By default, this transition subclass
operates as a shared element transition,
meaning the Android transition system is
able to pick up two views and different layouts
when marked with a transition name.
We first need to add a transitionName attribute
on the material card view in Email Item layout.
The transitionName takes in a string resource
with a parameter.
We need to use the ID of each email
to ensure each transition name in our EmailFragment is unique.
Note that this attribute is available from API 24 onwards.
Use the view compact.set transitionName method
if your minSdk is below 24.
We need to do the same in the email details layouts.
In fragment Email, set the transition name
of the material card view.
In HomeFragment in onEmailClicked,
create the mapping from our start view, the email list
item, and end view, the email details screen.
We're using FragmentNavigatorExtras here
from the navigation components to create
a mapping between the cardViewTransitionName
and the transitionName string parsed
in as the second parameter, emailCardDetailTransitionName.
This is how the system knows which views to find and provide
to the MaterialContainerTransform
instance as the start and end views to transform between.
With the plumbing complete, we can now
create a container transform.
In the EmailFragments onCreate method,
set shared elements into transition
to a new instance of a MaterialContainerTransform.
We're using drawingViewId to ensure the transition is drawn
below the bottom app bar and FAB,
specifying a longer duration, setting a transparent scrim,
and using colorSurface for all transition containers.
Let's rerun our app and see how it looks.
Looks pretty good.
When we click on an email in the email list,
a container transform expands the list item
into a full screen details page.
However, notice how pressing Back
doesn't collapse the email back into the list.
Additionally, the email list disappears immediately
at the beginning of the transition,
showing the gray window background.
So we're not done yet.
To fix the return transition, add these two lines
to the onViewCreated callback in HomeFragment.
We're basically scheduling our transitions
until after the recycler view has been populated with emails
and the transition is able to find the mappings
we configured.
The issue of the email list disappearing
is because when navigating to a new fragment using
the navigation components, the current fragment is immediately
removed and replaced with our new incoming fragment.
To keep the email list visible even after being replaced,
we can add an exit transition to HomeFragment.
MDC provides two transitions to do this for us,
Hold and MaterialElevationScale.
The Hold transition simply keeps its target
in its current position, while MaterialElevationScale
runs a subtle scale animation.
We'll use MaterialElevationScale as an exit transition
and re-enter transition.
We also need to mark the recycler
view in fragment Home as a transition group
to ensure the transition is applied to the home screen
as a whole.
Note that this attribute is available from API 24 onwards.
Use the view group compacts.set transition group method
if your minSDK is below 24.
Now let's rerun our app.
We now have a fully working container transform.
Clicking on an email expands the list item into a detail screen
while receding the list of emails.
Pressing Back collapses the email details screen
back into a list item while scaling up
in the list of emails.
Let's continue with container transform and add a transition
from the FAB to ComposeFragment, expanding it to a new email
to be written by the user.
The way we'll configure this instance
will be different, since our FAB lives in main activity
and our ComposeFragment is placed inside our main activity
navigation host container.
In ComposeFragment, let's add an enter transition
and a return transition in the onViewCreated callback.
We're using similar parameters used
to configure our previous container transform.
Notice that we've also specified our start view and end
view manually.
Instead of using transition name attributes
to let the Android transition system know which view should
be transformed, we can specify these manually when necessary.
Now let's rerun the app.
The FAB transforms into the Compose screen.
Similar to the previous step, we need
to add a transition to HomeFragment to keep it
from disappearing after being removed and replaced
by a ComposeFragment.
We'll add an exit transition and a re-enter transition
and use MaterialElevationScale as we did before.
Notice we're using the same duration
as the MaterialContainerTransform
so that they're choreographed correctly.
Let's rerun the app again.
That's it for this step.
Our transition looks great and clearly communicates
the relationship between the FAB and the Compose screen.
Next, we'll add a transition from the Search icon
to the full screen search view.
Since there is no persistent container involved
in this navigation change, we can
use a shared z-axis transition to reinforce
the spatial relationship between the two screens
and indicate moving one level upward in the app's hierarchy.
We'll add an exit transition and a re-enter transition
to our current NavigationFragment
in main activity, and use the MaterialSharedAxis class.
We specify the z-axis and whether the transitions
are going forward or backward.
We also adjust the duration like we've done before.
In SearchFragment, we do exactly the same
in the onCreate callback.
Lastly, in order to ensure that the MaterialSharedAxis
transition is applied to the search screen as a whole
instead of to each of the individual views
in the hierarchy, we mark the LinearLayout in fragment
Search as a transition group.
Now let's rerun the app.
That looks great.
Tapping the Search icon causes the home and search
view screens to simultaneously fade and scale
along the z-axis in depth, creating a seamless effect
between the two screens.
The next step is to add a transition
between different mailboxes.
Since we don't want to emphasize a spatial or hierarchical
relationship, we'll use a fade through
to perform a simple swap between lists of emails.
We'll add an exit transition to our currentNavigationFragment
in main activity and use the MaterialFadeThrough class.
We adjust the duration like we've done before.
We'll do the same in the onCreate callback
in HomeFragment, except this time we'll
specify the enter transition.
Now let's rerun the app.
Nice.
When opening the bottom navigation drawer
and changing the mailboxes, the current list of emails
fade and scale out while the new list fades and scales in.
In the final step, we'll add a transition that transforms
a chip into a pop-up card.
The container transform is used here
to help inform the user that the action taken in the pop-up
will affect the chip from which the pop-up originated.
We've mainly been dealing with fragments so far,
but this will be an example of a view to view transition.
Already added in the ComposeFragment layout
are recipient chips, visible by default,
and a recipient called, invisible by default.
A recipient chip and this card are the two views we'll create
a container transform between.
In ComposeFragment in the expandChip method,
we'll instantiate a MaterialContainerTransform
and register it with TransitionManage
r.beginDelayedTransition.
We are specifying an end elevation,
as the chip is unelevated, whereas the card isn't.
We're also specifying a target for you
to prevent the transition running on both views, which
is the default behavior.
Next, let's configure the return transition to collapse the card
back into the chip.
In the collapseChip method, we'll
add a similar looking MaterialContainerTransform
and once again use Transition Manager.beginDelayedTransition.
Notice here that instead of end elevation,
we're specifying start elevation.
Now let's rerun the app.
That's a big improvement.
Clicking the chip expands it into a card,
while clicking the card will collapse it back into a chip.
That's it for today's episode.
We saw how to implement the full Material Motion transition
patterns with fragments, activities, and views
using the MDC classes and our Reply sample app.
Each transition pattern is suited better
to certain scenarios, and we saw where it's best
to use container transform, shared axis,
fade through, and fade.
If you like the video, go ahead and like, share,
and subscribe to the Android Developers Channel on YouTube.
Thanks.
[MUSIC PLAYING]