写在前面
本文是对 Material Motion过渡模式的使用进行总结, 适用于已经明白过渡模式的使用但忘记具体代码实现的开发者. 本文用例基于 androidx
和 kotlin
. 详细完整教程请查阅: material-motion-android.
一. 简介
material-motion-android 是MDC-Android库中的一组过渡模式; 其中主要包含四种过渡模式:
Container Transform
: 包含container
的UI元素之间的转换 在两个不同的UI元素之间创建可见连接, 使一个UI元素无缝过渡到另一个UI元素.Shared Axis
: 具有空间或导航关系的UI元素之间的过渡; 在x, y或z轴上使用共享变换来加强元素之间的关系.Fade Through
: 在彼此之间没有密切关系的UI元素之间进行过渡; 使用顺序淡入和淡入, 以及传入元素的比例.Fade
: 用于在屏幕范围内进入或退出的UI元素.
MDC-Android库在AndroidX Transition库(androidx.transition
)和 Android Transition Framework(android.transition
)的基础上,为这些模式提供了转换类 :
-
AndroidX (
androidx.transition
)- 在
com.google.android.material.transition
包下; - 支持API14及以上;
- 支持
Fragments
和Views
, 不支持Activityies
和Windows
; - 包含反向移植的错误修复程序和跨API级别的一致行为;
- 依赖:
implementation 'com.google.android.material:material:1.2.1'
- 在
-
Framework (
android.transition
)- 在
com.google.android.material.transition.platform
包下; - 支持API21及以上;
- 支持
Fragments
|Views
|Activityies
|Windows
; - 错误修复未向后移植, 并且在各个API级别上可能具有不同的行为;
- 在
本文使用 AndroidX Transition
库; Fragments
由 navigation
库导航.
二. Container Transform
过渡模式
- 核心类
MaterialContainerTransform
; - 本用例为跳转的目标Fragment中包含
Container
- 通过
transitionName
标记, 使过渡系统在不同布局获取两个控件;- 在API 21以上可以直接使用
android:transitionName
; - 如果支持API 21 以下使用
ViewCompat
#setTransitionName
方法; - 对于
RecyclerView
中的item
布局中的控件,transitionName
不能相同;
- 在API 21以上可以直接使用
- 点击
RecyclerView
item
跳转Fragment
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
的onCreate
中添加sharedElementEnterTransition (Fragmen.setSharedElementEnterTransition())
,完成这一步便实现了跳转新Fragment
的过渡sharedElementEnterTransition = MaterialContainerTransform().apply { drawingViewId = R.id.nav_host_fragment duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong() scrimColor = Color.TRANSPARENT setAllContainerColors(requireContext().themeColor
- 通过