One of the main features in Material Design is the transition of elements and components to express relationships between them or outcomes and availability for actions.
材料设计的主要功能之一是元素和组件之间的过渡,以表达它们之间的关系或结果与操作的可用性。
Since 1.2.0-alpha05 version, Material Components for Android library has incorporated Transitions and Motion. They are an easy-to-use set of classes to implement different type of customizable transitions and animations.
从1.2.0-alpha05版本开始, Android库的Material Components已合并了Transitions和Motion。 它们是一组易于使用的类,用于实现不同类型的可自定义过渡和动画。
There are different transition patterns that comprised the Material Design motion system for transitioning between components or full-screen views.
材料设计运动系统由不同的过渡模式组成,用于在零部件或全屏视图之间过渡。
What’s really important is choosing which transition pattern is appropriate for each use case.
真正重要的是选择适合每个用例的过渡模式。
The transition patterns are:
过渡模式为:
Container transform: It’s used in transitions that involve a persistent element such as a list, card surface or button.
容器转换:用于涉及持久性元素(例如列表,卡片表面或按钮)的转换。
- Shared axis: It’s used for transitions between UI elements that have a spatial or navigational relationship. 共享轴:用于具有空间或导航关系的UI元素之间的过渡。
- Fade through: When a relationship between elements is insignificant or does not exist. 淡入淡出:元素之间的关系不明显或不存在时。
- Fade: It’s is applied in the UI elements that need to enter or exit the screen. 淡入淡出:在需要进入或退出屏幕的UI元素中应用。
Recently, I’ve been working on some samples that use Material Design motion system.
最近,我一直在研究一些使用Material Design运动系统的示例。
implementation('com.google.android.material:material:1.2.0-beta01')
容器变换 (Container Transform)
This pattern is used to create a visible connection between two UI elements. It transforms one element into another. This is a common UX pattern to express that one element is related with another as item-detail container. For instance, if a card item in a list transforms into a detail view, the user perceives that the detail page is an extended version of the card.
此模式用于在两个UI元素之间创建可见的连接。 它将一个元素转换为另一个元素。 这是一种常见的UX模式,用于表示一个元素与另一个元素相关联,作为项详细信息容器。 例如,如果列表中的卡片项目转换为详细信息视图,则用户会认为详细信息页面是卡片的扩展版本。
This could be also used as a transformation of a FAB button into a menu or a sheet.
这也可以用作将FAB按钮转换为菜单或工作表的方式。
This transition can be applied between activities, fragments or views, depending on whether we want to transform a view of one activity or fragment in another activity, fragment or view.
可以在活动,片段或视图之间应用此过渡,具体取决于我们是否要在另一个活动,片段或视图中转换一个活动或片段的视图。
This transformation is fully customizable by specifying different values for properties that affect the transition.
通过为影响过渡的属性指定不同的值,可以完全自定义此变换。
duration
持续时间
Sets the duration of this transition in milliseconds.
设置此过渡的持续时间(以毫秒为单位)。
interpolator
内插器
Sets the interpolator of this transition. We can specify some interpolator like FastOutSlowIn or custom using PathInterpolator for a cubic Bezier curve.
设置此过渡的插值器。 我们可以指定一些插值器,例如FastOutSlowIn或使用PathInterpolator自定义三次贝塞尔曲线。
fadeMode
fadeMode
Sets the fade mode to be used to switch the content of the start view with that of the end view. There are four fade modes:
设置淡入淡出模式,用于将开始视图的内容与结束视图的内容切换。 有四种淡入淡出模式:
- FADE_MODE_IN
: Fade the incoming content without change the opacity of outgoing content. This is the default mode.
FADE_MODE_IN
:淡入传入内容,而不更改传出内容的不透明度。 这是默认模式。
- FADE_MODE_OUT
: Fade the outgoing content without change the opacity of incoming content.
FADE_MODE_OUT
:淡出输出内容而不更改输入内容的不透明度。
- FADE_MODE_CROSS
: Cross-fade the incoming and outgoing content.
FADE_MODE_CROSS
:淡入淡出传入的内容。
- FADE_MODE_THROUGH
: Sequentially fade out the outgoing content and fade in the incoming content.
FADE_MODE_THROUGH
: FADE_MODE_THROUGH
淡出输出内容并淡入输入内容。
fitMode
fitMode
There are three options:
共有三个选项:
- FIT_MODE_HEIGHT
: Fit the incoming content to the height of the outgoing content during the scale animation.
FIT_MODE_HEIGHT
:在缩放动画期间,将传入内容调整为传出内容的高度。
- FIT_MODE_WIDTH
: Fit the incoming content to the width of the outgoing content during the scale animation.
FIT_MODE_WIDTH
:在缩放动画过程中,使传入内容适合传出内容的宽度。
- FIT_MODE_AUTO
: Use FIT_MODE_HEIGHT or FIT_MODE_WIDTH automatically.
FIT_MODE_AUTO
:自动使用FIT_MODE_HEIGHT或FIT_MODE_WIDTH。
containerColor
containerColor
Sets the background color of the morphing container. This color is drawn below the start and end views. This is very useful when one or both do not have a solid color background. This can be also used to set the color of transition to enhance the transformation from one view into another.
设置变形容器的背景颜色。 此颜色绘制在开始视图和结束视图下方。 当一个或两个都不具有纯色背景时,这非常有用。 这也可以用来设置过渡的颜色,以增强从一种视图到另一种视图的转化。
scrimColor
scrimColor
Sets the color to be drawn under the morphing container within bounds of the drawingView.
设置要在drawingView范围内的变形容器下绘制的颜色。
The drawingView is the view to which the transition will overlap. This drawingView can be specified using the setDrawingViewId()
function.
drawingView是过渡将与之重叠的视图。 可以使用setDrawingViewId setDrawingViewId()
函数指定此drawingView。
private fun buildContainerTransform() =
MaterialContainerTransform().apply {
addTarget(binding.coordinator)
duration = 500
fadeMode = MaterialContainerTransform.FADE_MODE_IN
interpolator = FastOutSlowInInterpolator()
}
FAB到菜单 (FAB to Menu)
This transition transforms a FAB into a menu. We will specify which is the start and end view.
此转换将FAB转换为菜单。 我们将指定哪个是开始视图和结束视图。
private fun buildContainerTransformation() =
MaterialContainerTransform().apply {
scrimColor = Color.TRANSPARENT
duration = 300
interpolator = FastOutSlowInInterpolator()
fadeMode = MaterialContainerTransform.FADE_MODE_IN
}
private fun setClickListeners() {
binding.floatingActionButton.setOnClickListener {
val transition = buildContainerTransformation()
transition.startView = binding.floatingActionButton
transition.endView = binding.card
transition.addTarget(binding.card)
TransitionManager.beginDelayedTransition(findViewById(android.R.id.content), transition)
binding.card.visibility = View.VISIBLE
binding.fabScrim.visibility = View.VISIBLE
binding.floatingActionButton.visibility = View.INVISIBLE
}
}
FAB到活动 (FAB to Activity)
This transition transforms a FAB into an Activity. It uses the MaterialArcMotion
to move the container along a curve.
此转换将FAB转换为活动。 它使用MaterialArcMotion
沿曲线移动容器。
private fun buildContainerTransform() =
MaterialContainerTransform().apply {
addTarget(binding.coordinator)
setAllContainerColors(MaterialColors.getColor(binding.root, R.attr.colorSurface))
pathMotion = MaterialArcMotion()
duration = 500
interpolator = FastOutSlowInInterpolator()
fadeMode = MaterialContainerTransform.FADE_MODE_IN
}
MaterialCard查看活动 (MaterialCardView to Activity)
Transform a list item into an Activity. We can observe the difference between FADE_MODE_IN
and FADE_MODE_OUT
.
将列表项转换为活动。 我们可以观察到FADE_MODE_IN
和FADE_MODE_OUT
之间的区别。
inner class ViewHolder(val binding: ItemNoteBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(note: Note) {
binding.note = note
binding.noteCard.transitionName = note.id.toString()
binding.noteCard.setOnClickListener {
noteClickListener.onNoteClick(note.id, binding.noteCard)
}
}
}
val adapter = NotesAdapter(notes)
adapter.noteClickListener = object : NotesAdapter.NoteClickListener {
override fun onNoteClick(id: Int, noteCard: MaterialCardView) {
val intent = Intent(this@NotesActivity, NoteDetailActivity::class.java)
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(
this@NotesActivity, noteCard, id.toString()
)
intent.putExtra("noteId", id)
startActivity(intent, options.toBundle())
}
}
class NoteDetailActivity : AppCompatActivity() {
private lateinit var binding: NoteDetailActivityBinding
override fun onCreate(savedInstanceState: Bundle?) {
window.requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)
binding = NoteDetailActivityBinding.inflate(layoutInflater)
val noteId = intent.getIntExtra("noteId", 0)
val note = notes.find { it.id == noteId }
binding.note = note
binding.coordinator.transitionName = noteId.toString()
setEnterSharedElementCallback(MaterialContainerTransformSharedElementCallback())
window.sharedElementEnterTransition = buildContainerTransform()
window.sharedElementReturnTransition = buildContainerTransform()
setContentView(binding.root)
super.onCreate(savedInstanceState)
}
private fun buildContainerTransform() =
MaterialContainerTransform().apply {
addTarget(binding.coordinator)
duration = 300
interpolator = FastOutSlowInInterpolator()
fadeMode = MaterialContainerTransform.FADE_MODE_IN
}
}
Android导航组件中的容器转换 (Container Transform in Android Navigation Component)
val adapter = AlbumsAdapter(albums, requireContext())
adapter.albumClickListener = object : AlbumsAdapter.AlbumClickListener {
override fun onAlbumClick(id: Int, cardView: MaterialCardView) {
val extras = FragmentNavigatorExtras(
cardView to id.toString()
)
val action = AlbumsFragmentDirections.navToAlbumFragment(id)
findNavController().navigate(action, extras)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sharedElementEnterTransition = buildContainerTransform()
sharedElementReturnTransition = buildContainerTransform()
}
private fun buildContainerTransform() =
MaterialContainerTransform().apply {
drawingViewId = R.id.nav_host_fragment
interpolator = FastOutSlowInInterpolator()
containerColor = Color.WHITE
fadeMode = MaterialContainerTransform.FADE_MODE_OUT
duration = 300
}
共享轴 (Shared Axis)
This pattern is used for transitions between UI elements that have a spatial or navigational relationship. It uses a transformation on the x, y, or z axis to reinforce the relationship between elements. By moving in the same direction, elements are perceived to be related to each other.
此模式用于具有空间或导航关系的UI元素之间的过渡。 它使用x,y或z轴上的变换来增强元素之间的关系。 通过沿相同方向移动,可以将元素视为相互关联。
val forward = true
val fragment = MyFragment.newInstance()
// axis: MaterialSharedAxis.X, Y or Z
// forward: true if it move in the forward direction or false if it move in the backward direction
fragment.enterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, forward)
supportFragmentManager
.beginTransaction()
.replace(R.id.fragment_container, fragment)
.commit()
X轴 (X-axis)
An example of using MaterialSharedAxis transition on the X-axis for an application walkthrough.
在X轴上使用MaterialSharedAxis过渡进行应用程序遍历的示例。
Y轴 (Y-axis)
A vertical stepper using MaterialSharedAxis transition on the Y-axis.
在Y轴上使用MaterialSharedAxis过渡的垂直步进器。
Z轴 (Z-axis)
Z-axis transitions indicate moving one level upward or downward in an app’s hierarchy.
Z轴过渡指示在应用程序的层次结构中向上或向下移动一个级别。
淡入淡出 (Fade through)
This pattern is used for transitions between UI elements that do not have a strong relationship to each other.
此模式用于在彼此之间没有密切关系的UI元素之间的过渡。
The fade through is the best choice in a bottom navigation view because destinations are often grouped into major tasks that may not relate to one another.
在目的地导航视图中,淡入淡出是最佳选择,因为目的地通常被分组为可能彼此不相关的主要任务。
class ArtistsFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialFadeThrough()
}
...
}
褪色 (Fade)
This pattern is used for UI elements that enter or exit within the bounds of the screen, such as a dialog that fades in and out of view from the center.
此模式用于在屏幕范围内进入或退出的UI元素,例如从中心淡入或淡出对话框的对话框。
// import androidx.transition.TransitionManager
binding.floatingActionButton.post {
val transition = MaterialFade().apply {
duration = 1500
}
TransitionManager.beginDelayedTransition(binding.root, transition)
binding.floatingActionButton.visibility = View.VISIBLE
}
文档和帮助 (Documentation and help)
翻译自: https://proandroiddev.com/material-design-motion-for-android-396da62edb1c