共计 5838 个字符,预计需要花费 15 分钟才能阅读完成。
近期公布的 Material 动效零碎 是 MDC-Android 库 (v 1.2.0) 的一部分,它将罕用的过渡成果演绎为一组简略的模式,提供更晦涩更加容易了解的用户体验。Material 动效目前包含四种过渡成果:
- 容器转换 (Container transform)
- 共享轴 (Shared axis)
- 淡入淡出 (Fade through)
- 褪色 (Fade)
咱们曾经在 Android 平台 和 AndroidX 过渡零碎 实现了以上过渡成果,以便在 Activity、Fragment 和 View 之间切换时轻松应用。
本文会介绍下面每种模式,并解释如何将这些模式利用到您的利用中。我将会通过在示例利用 Reply (一个简略易用的邮件客户端) 中实现对应的成果来阐明每个步骤。Reply 利用的三个操作流程会应用到这些过渡动效: 关上邮件 、 关上搜寻页面 、 切换信箱。
如果您不满足于上手介绍,更心愿深刻源码,请参阅 Material 动效 Codelab,按步骤上手实际这项技术,Codelab 也提供了在 Android 上应用这些过渡成果的其余信息。
容器转换: 关上邮件
容器转换是过渡的配角,容器转换用在将一个元素转换为另一个元素。什么意思呢?例如示例的一个列表开展成为了详情页、FAB 变形为工具栏,或 chip 扩大为了浮动的 卡片。在每个场景中都有一个组件变换为另一个组件,并以动画形式切换 “ 外部 ” 内容,同时保护一个共享的 “ 内部 ” 容器。应用容器变换,实现视图间的动画切换,可帮忙加强它们之间的分割,并维持一个用户的 导航上下文。
在 Reply 示例中,咱们在展现邮件列表的 Fragment (HomeFragment) 和邮件详情 Fragment (EmailFragment) 间增加了容器转换。如果您相熟 Android 共享元素过渡,它与容器转换的设置十分类似。
首先,确定两个共享元素的视图,并为每一个视图增加 过渡名称。第一个是单个邮件列表项的卡片,咱们将应用 数据绑定,来确保每一个列表项都有惟一的过渡名称。
android:transitionName="@{@string/email_card_transition_name(email.id)}"
第二个是 EmailFragment 外部的全屏卡片组件,这个组件能够设置一个动态的过渡名称,因为在视图层级中只有这一个视图。留神,两个共享元素不须要应用雷同的过渡名称。
这两个视图会被咱们的容器转换应用。工作原理是: 它们都会被放在一个 drawable 外部,此 drawable 的边界会被裁剪到 “ 容器 ” 中,而 “ 容器 ” 会将本人的形态通过动画从一个列表项转换为详情页。在过渡过程中,通过传入页面在传出屏幕上淡入,容器的内容 (列表项和详情页) 产生了替换。
当初咱们曾经标记了共享元素的视图,接下来就能够创立目的地 Fragment 的 sharedElementEnterTransition
,并将其设置给一个 MaterialContainerTransform
的实例。默认状况下,从详情页面返回时,这个 sharedElementEnterTransition 会主动反转并播放。
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))
}
无关
MaterialContainerTransform
参数的详细信息,请参阅 动效文档
当一封邮件被点击时,咱们所有须要做的就是为 Fragment 事务提供开始视图和完结视图过渡名称之间的映射。有了这些信息,邮箱详情 Fragment 共享元素过渡就能够应用咱们提供的 MaterialContinaerTransform 找到并在两个视图之间进行动画切换。
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)
}
在下面的代码片段中,咱们也为传出页邮件 列表 Fragment 设置了
exit
和reenter
的过渡成果。Material 组件提供了两个过渡辅助: Hold 和 MaterialElevationScale,以平滑地为将要被替换的 Fragment 设置动画。除了褪色 (Fade),MaterialElevationScale 还会在邮件列表页退出时,对其进行缩放,并在从新进入邮件列表时缩放回来。Hold 仅仅是简略地保留邮件列表。如果没有设置退出时的过渡,咱们的邮件列表会被立即删除并从视图中隐没。
如果咱们在这个时候运行代码,从详情页导航返回到邮件列表页,则返回过渡不会执行。这是因为当过渡开始时,邮件列表的适配器还未被填充,过渡零碎找不到与过渡名称对应的两个视图。侥幸的是,有两个简略办法可供咱们应用: postponeEnterTransition 和 startPostponedEnterTransition。这两个办法容许咱们提早过渡,直到咱们晓得咱们的共享元素曾经被布局,并且能够被过渡零碎发现。在 Reply 利用中,咱们能够应用以下代码提早过渡,直到咱们确定 RecyclerView 适配器已被填充,列表项已和过渡名称绑定:
postponeEnterTransition()
view.doOnPreDraw {startPostponedEnterTransition() }
在您本人的利用中,您可能须要尝试这两种办法,以依据您填充 UI 的形式和工夫,来找到适合的工夫开始提早过渡。如果您发现您的返回动画没有执行,可能是在共享元素就绪之前开始了过渡。
接下来进入咱们的搜寻页面。
共享轴: 关上搜寻页面
共享轴模式用于有空间和导航关系的 UI 元素之间的过渡。在 Reply 利用中,关上搜寻页面会将用户带到邮件列表顶部的新页面。为了介绍这个三维模型,咱们能够在邮件列表 (HomeFragment) 和搜寻页面 (SearchFragment) 之间应用共享 z 轴过渡。
共享轴过渡会在操作两个指标的同时创立最终的、编排过的过渡成果。这意味着 “ 成对 ” 的过渡会一起运行去创立间断的定向的动画。对 Fragment 来说,这成对的过渡包含:
- FragmentA 的
exitTransition
和 FragmentB 的enterTransition
- FragmentA 的
reenterTransition
和 FragmentB 的returnTransition
MaterialSharedAxis 是实现了共享轴模式的类,它接管 forward 属性来管制方向性的概念。在每一个过渡配对中,forward 必须被设置为雷同的值,以便正确地协调这对动画。
如需理解更多对于共享轴方向性的详细信息,请查阅 动效文档。
在 Reply 利用中,这是咱们为以后的 Fragment (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()}
}
在咱们目标 fragment (SearchFragment) 中,咱们建设进入和返回的过渡。
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()}
留神: 以后 Fragment 的退出过渡和搜寻 Fragment 的进入过渡应用雷同的 forward 值 – true,以后 Fragment 的重入过渡和搜寻 Fragment 的返回过渡也是如此。
接下来,默认状况下,过渡会在场景根层次结构内的所有子视图上运行,这意味着一个共享轴过渡会利用于邮件列表上的每一封邮件以及搜寻页面的每一个子视图。如果您想要 “ 流传 ” 或者 “ 错开 ” 动画,这是一个十分好的性能,然而因为咱们须要对每个 Fragment 的根作为整体进行动画解决,咱们须要在 邮件列表的 RecyclerView 和咱们的 搜寻页面的根 view group 设置 android:transitionGroup=”true”。
这样,咱们就在进出搜寻页面时有了一个丑陋的共享 z 轴过渡!共享轴是一个非常灵活的过渡,能够利用于许多不同的场景,从页面过渡到智能回复抉择,再到进入或者垂直的步骤流程。您曾经配置好了设置,还能够尝试应用 MaterialSharedAxis 的 axis 参数来理解其余轴动画是什么样子。
淡入淡出: 切换邮箱
咱们要介绍的最初一个模式是淡入淡出模式。淡入淡出可用于在没有强关系的 UI 元素间过渡。当在两个信箱之间过渡时,咱们不心愿用户认为他们曾经发送的邮件和他们的收件箱在导航上相干。因为每个信箱是一个顶级的目的地,淡入淡出是一个适合的抉择。在 Reply 利用中,咱们将用不同的电子邮件列表 (带有新参数的 HomeFragment) 替换电子邮件列表 (HomeFragment)。
因为 MaterialFadeThrough 没有方向性,所以设置起来更加简略。咱们只须要为传出 Fragment 设置一个退出过渡,为传入 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()}}
在 邮件列表的 RecyclerView 上设置 android:transitionGroup=”true” 的需要同样实用于这里,然而咱们曾经在共享轴配置的步骤中解决了这个问题。
以上就是淡入淡出过渡!您能够在本人我的项目乏味的中央来应用淡入淡出模式,比方: 底部导航栏的切换、列表项的替换,或替换一个工具栏菜单。
裹足不前!
本文简要介绍了 Android 的 Material 动效零碎。通过应用该零碎所提供的模式,您能够在自定义动效时,做很多事件,使动效成为品牌体验的一部分。本文咱们看到了 Fragment 的过渡,但动效零碎也可用于 Activity 甚至 View 间的过渡。查看残缺的 动效标准 文档,取得更多启发,以便思考哪些地方可进步您利用的外围体验,或在一些小的中央减少额定的乐趣。
持续学习,请查看以下其余资源:
- Material 动效开发文档: 您能够在 Material Android 动效文档找到许多对于在 Activity 和 View 之间进行动画的自定义选项和倡议。
- Material 动效 Codelab: 一个残缺的分步的开发者教程,内容波及如何在 Reply 利用中增加 Material 动效。
- Android Google 云盘: 您能够在 Android Google 云盘利用中看到正在运行的动效零碎。点击文件夹、关上搜寻、在底部导航间切换,这些都用到了 MDC-Android 的过渡成果。