头图

The recently released Material motion system is part of the MDC-Android library (v 1.2.0) , which summarizes the commonly used transition effects into a set of simple modes, providing a smoother and easier-to-understand user experience. Material animation currently includes four transition effects:

We have Android platform and AndroidX transition system , so that they can be easily used when switching between Activity, Fragment and View.

This article will introduce each of the above modes and explain how to apply these modes to your application. I will illustrate each step by implementing the corresponding effect in the sample application Reply (a simple and easy-to-use mail client). The three operation processes of the Reply application will use these transition effects: open mail , open search page , switch mailbox .

If you are not satisfied with the introduction and want to go deeper into the source code, please refer to Material Motion Codelab , follow the steps to practice this technology, Codelab also provides other information on using these transition effects on Android.

container conversion: open mail

Container transformation is the protagonist of transition, and container transformation is used to transform one element into another. What does that mean? For example, a list of the example expands into a detail page, FAB transformed into a toolbar, or chip expanded to a floating card . In each scene, one component transforms into another component, and the "internal" content is switched in an animated manner, while maintaining a shared "external" container. Using container transformations to achieve animation switching between views can help enhance the connection between them and maintain a user’s navigation context .

In the Reply example, we added a container conversion between the Fragment showing the mailing list ( HomeFragment ) and the email detail Fragment ( EmailFragment If you are familiar with the Android shared element transition , it is very similar to the container conversion settings.

First, determine the views of the two shared elements, and add transition name to each view. The first is a card for a single mailing list item. We will use the data binding to ensure that each list item has a unique transition name.

android:transitionName="@{@string/email_card_transition_name(email.id)}"

The second is EmailFragment . This component can be set with a static transition name because there is only one view in the view hierarchy. Note that the two shared elements do not need to use the same transition name.

These two views will be converted to use by our container. The working principle is: they are all placed inside a drawable, the border of this drawable will be cropped into the "container", and the "container" will transform its shape from a list item to a detail page through animation. During the transition process, the content of the container (list item and detail page) is exchanged by fading in the incoming page on the outgoing screen.

Now that we have marked the view of the shared element, we can create the sharedElementEnterTransition destination Fragment and set it to an instance of MaterialContainerTransform By default, when returning from the details page, this sharedElementEnterTransition will be automatically reversed and played.

sharedElementEnterTransition = MaterialContainerTransform().apply {
   //  drawingViewId 是视图的 id,在其上方,容器变换将在 z 轴空间进行
   drawingViewId = R.id.nav_host_fragment
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   // 由于我们也想将列表页面通过动画转换出视图,所以将 scrimColor 设置为透明
   scrimColor = Color.TRANSPARENT
   setAllContainerColors(requireContext().themeColor(R.attr.colorSurface))
}
For detailed information about the MaterialContainerTransform , please refer to the dynamic document

When an email is clicked, all we need to do is provide a mapping between the start view and the end view transition name for the Fragment transaction. With this information, the mailbox detail Fragment shared element transition can be found and animated between the two views using the MaterialContinaerTransform we provide.

override fun onEmailClicked(cardView: View, email: Email) {
     exitTransition = MaterialElevationScale(false).apply {
         duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
     }
     reenterTransition = MaterialElevationScale(true).apply {
           duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
     }
     val emailCardDetailTransitionName = getString(R.string.email_card_detail_transition_name)
     val extras = FragmentNavigatorExtras(cardView to emailCardDetailTransitionName)
     val directions = HomeFragmentDirections.actionHomeFragmentToEmailFragment(email.id)
     findNavController().navigate(directions, extras)
 }
In the above code snippet, we also set the transition effect exit and reenter The Material component provides two transition aids: Hold and MaterialElevationScale to be replaced. In addition to fading, MaterialElevationScale will also zoom when the mailing list page exits, and zoom back when re-entering the mailing list. Hold simply keeps the mailing list. If there is no transition at exit, our mailing list will be deleted immediately and disappear from view.

If we run the code at this time and navigate back to the mailing list page from the details page, the return transition will not be performed. This is because when the transition starts, the adapter of the mailing list has not been filled, and the transition system cannot find the two views corresponding to the transition name. Fortunately, there are two simple methods available to us: postponeEnterTransition and startPostponedEnterTransition. These two methods allow us to delay the transition until we know that our shared elements have been laid out and can be discovered by the transition system. In the Reply application, we can use the following code to delay the transition until we are sure that the RecyclerView adapter has been filled and the list items have been bound to the transition name:

postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }

In your own application, you may need to try these two methods to find the right time to start the delay transition based on how and when you fill the UI. If you find that your return animation is not executing, it may be that the transition started before the shared element was ready.

Next enter our search page.

Shared axis: Open the search page

The shared axis mode is used to transition between UI elements that have spatial and navigational relationships. In the Reply app, opening the search page will take the user to a new page at the top of the mailing list. To introduce this 3D model, we can use the shared z-axis transition between the HomeFragment ) and the search page ( SearchFragment

The shared axis transition creates the final, choreographed transition effect while manipulating two targets. This means that "pairs" of transitions will run together to create a continuous directional animation. For Fragment, this paired transition includes:

  • exitTransition FragmentA and enterTransition
  • reenterTransition FragmentA and returnTransition

MaterialSharedAxis is a class that implements the shared axis mode, and it receives the forward property to control the concept of directionality. In each transition pair, forward must be set to the same value in order to coordinate the pair of animations correctly.

For more detailed information about the directionality of the shared axis, please refer to the motion document .

In the Reply application, this is how we create exit and reentry transitions HomeFragment

currentNavigationFragment?.apply {
   exitTransition = MaterialSharedAxis(
      MaterialSharedAxis.Z, 
      /* forward= */ true
   ).apply {
      duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
   reenterTransition = MaterialSharedAxis(
      MaterialSharedAxis.Z, 
      /* forward= */ false
   ).apply {
       duration =resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
}

In our target fragment ( SearchFragment ), we establish the transition between entry and return.

enterTransition = MaterialSharedAxis(
   MaterialSharedAxis.Z, 
   /* forward= */ true
).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
returnTransition = MaterialSharedAxis(
   MaterialSharedAxis.Z, 
   /* forward= */ false
).apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}

Note: The exit transition of the current fragment and the entry transition of the search fragment use the same forward value-true, the same is true for the reentry transition of the current fragment and the return transition of the search fragment.

Next, by default, the transition will run on all subviews within the scene root hierarchy, which means that a shared axis transition will be applied to every message on the mailing list and every subview of the search page. If you want to "spread" or " staggered " animation, which is a nice feature, but because we need to root each Fragment animate as a whole, we need to RecyclerView mailing list and we The root view group of the search page is set to android:transitionGroup="true" .

In this way, we have a beautiful shared z-axis transition when we enter and exit the search page! The shared axis is a very flexible transition that can be applied to many different scenarios, from page transition to intelligent reply selection, to entry or vertical step flow. You have configured the settings, and you can also try to use MaterialSharedAxis to understand what other axis animations look like.

fade in and fade out: switch mailbox

The last mode we want to introduce is the fade-in and fade-out mode. Fade in and out can be used to transition between UI elements that are not strongly related. When transitioning between two mailboxes, we don't want users to think that the mail they have sent is related to their inbox navigation. Since each mailbox is a top destination, fade in and out is a suitable choice. In the Reply application, we will replace the email list ( HomeFragment HomeFragment with new parameters).

Because MaterialFadeThrough has no directionality, it is easier to set up. We only need to set an exit transition for the outgoing Fragment and an entry transition for the incoming Fragment.

currentNavigationFragment?.apply {
   exitTransition = MaterialFadeThrough().apply {
       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
   }
}
enterTransition = MaterialFadeThrough().apply {
   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}}

In RecyclerView mailing list set on Android: transitionGroup = "to true" demand the same applies here, but we have solved this problem in a step shared axis configuration.

The above is the fade transition! You can use the fade-in and fade-out mode in interesting places of your project, such as: switching the bottom navigation bar, swapping list items, or replacing a toolbar menu.

!

This article briefly introduces the Android's Material animation system. By using the modes provided by the system, you can do a lot of things when customizing motion effects, making motion effects a part of the brand experience. In this article, we have seen the transition of Fragment, but the animation system can also be used for the transition between Activity and even View. Check out the complete motion specification document to get more inspiration, so that you can think about what can improve the core experience of your application, or add extra fun in some small places.

To continue learning, check out the following other resources:

  • Material Animation Development Document : You can find many customization options and suggestions for animation between Activity and View in Material Android Animation Document.
  • Material Animation Codelab : A complete step-by-step developer's tutorial on how to add Material animation to the Reply application.
  • Android Google Cloud Disk : You can see the running dynamic system in the Android Google Cloud Disk application. Click the folder, open the search, switch between the bottom navigation, these all use the transition effect of MDC-Android.

Android开发者
404 声望2k 粉丝

Android 最新开发技术更新,包括 Kotlin、Android Studio、Jetpack 和 Android 最新系统技术特性分享。更多内容,请关注 官方 Android 开发者文档。