前沿:从一个新闻列表跳转到新闻详情页, 跳转的动画使用容器转换,如MainActivity下的RestFragment内部的嵌套的TabFragment跳转到NewsDetailFragment
一、listitem列表到详情界面的展开动画设置 设置transition_name属性 1、设置listitem 子布局(即需要展开的布局),布局根元素(看情况也不一定非要是根元素, 主要看情况想从哪个布局展开)的transition_name属性 2、设置新闻/作文等跳转后的详情界面(通常根元素)的transition_name属性 列表所在的碎片的跳转的监听中给action设置动画过渡参数TabRestFragment.kt
//跳转监听
//listitem 点击跳转到新闻详情界面,跳转参数为列表item的数据
override fun rvItemOnclick(viewRoot: View, news: Data?) {
if(news != null){
val newsCardDetailTransitionName = getString(R.string.news_card_detail_transition_name)
//R.string.news_card_detail_transition_name这个参数是目的地也就是详情界面所对应的transition_name属性值
val extras = FragmentNavigatorExtras(viewRoot to newsCardDetailTransitionName)
val actionRestFragmentToNewsDetailFragment: NavDirections =
RestFragmentDirections.actionRestFragmentToNewsDetailFragment(news)
this.findNavController().navigate(actionRestFragmentToNewsDetailFragment, extras)
}
}
详情界面碎片给过渡进行时长等设置
NewsDetailFragment.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sharedElementEnterTransition = MaterialContainerTransform().apply {
drawingViewId = R.id.nav_main_host_fragment
duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
scrimColor = Color.TRANSPARENT
setAllContainerColors(requireContext().themeColor(R.attr.colorSurface))
}
}
这里的themeColor来自Context拓展工具类
ContextExtensions.kt
package com.example.module_main.utils
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.util.TypedValue
import android.view.animation.AnimationUtils
import android.view.animation.Interpolator
import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.annotation.StyleRes
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.res.use
@ColorInt
@SuppressLint("Recycle")
fun Context.themeColor(
@AttrRes themeAttrId: Int
): Int {
return obtainStyledAttributes(
intArrayOf(themeAttrId)
).use {
it.getColor(0, Color.MAGENTA)
}
}
二、详情界面到listitem列表项的折叠动画设置
返回时折叠动画的设置
此时已经实现了从列表到详情页的扩展动画,但是此时返回时候切没有详情到列表的折叠动画
原因:
Typically, this first issue of the collapse not working is because when the Android Transition system is trying to run your return transition, the list of emails hasn’t been inflated and populated into the RecyclerView yet. We need a way to wait until our HomeFragment lays out our list before we start our transitions.
The Android Transition system provides methods to do just that - postponeEnterTransition and startPostponedEnterTransition. If postponeEnterTransition is called, any entering transition to be run will be held until a closing call to startPostponedEnterTransition is called. This gives us the opportunity to “schedule” our transitions until after the RecyclerView has been populated with emails and the transition is able to find the mappings you configured.
解决方案: (注意到根碎片也就是MainActivity下的RestFragment,而不是TabRestFragment)下添加两行代码
注意我这里是因为承载recyclerview的碎片是TabRestFragment,而TabRestFragment是RestFragment里面的的嵌套碎片所以在这里设置
谷歌原代码不存在嵌套,谷歌做法是直接在承载recyclerview的碎片也就是TabRestFragment中设置
// 尝试运行您的返回转换时,电子邮件列表尚未膨胀并填充到其中RecyclerView。HomeFragment在开始转换之前,我们需要一种方法来等待我们列出我们的列表。
// 如果postponeEnterTransition被调用,任何要运行的进入转换将被保持,直到调用结束调用startPostponedEnterTransition。这使我们有机会“安排”我们的转换,直到RecyclerView用电子邮件填充并且转换能够找到您配置的映射之后。
postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }
如下:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//进入方法首行设置
//解决点击返回后没有折叠的动画效果,注意这里一定要在加载完了背景视图和里面嵌套视图后设置,否则会同时出现先加载其他布局和显示动画
// 尝试运行您的返回转换时,电子邮件列表尚未膨胀并填充到其中RecyclerView。HomeFragment在开始转换之前,我们需要一种方法来等待我们列出我们的列表。
// 如果postponeEnterTransition被调用,任何要运行的进入转换将被保持,直到调用结束调用startPostponedEnterTransition。这使我们有机会“安排”我们的转换,直到RecyclerView用电子邮件填充并且转换能够找到您配置的映射之后。
postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }
//...
}
白屏详情数据(即解决点击返回直接白屏然后切回列表页面)
从列表跳转到详情页的展开动画进行的时候,跳转列表的其他列表消失不见显示白色,实际上就是设置整个fragment界面的进出动画
电子邮件列表消失的问题是因为当使用导航组件导航到一个新的 Fragment 时,当前的 Fragment 会立即被删除并替换为我们新传入的 Fragment。为了在被替换后仍保持电子邮件列表可见,您可以将退出转换添加到HomeFragment.
MDC-Android 提供了两种转换来为您执行此操作 -Hold和MaterialElevationScale. 该Hold过渡只是保持其目标在当前位置,同时MaterialElevationScale运行的微妙尺度动画。
注意在根布局设置,且最好在页面绘制的最后一行写,否则会会出现点击返回按钮后,详情界面立马先白屏,白屏后然后才折叠
//设置进出动画,避免列表跳转到详情页除了该列表其他部分白屏的情况
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()
}
RestFragmenet.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//进入方法首行设置
//解决点击返回后没有折叠的动画效果,注意这里一定要在加载完了背景视图和里面嵌套视图后设置,否则会同时出现先加载其他布局和显示动画
// 尝试运行您的返回转换时,电子邮件列表尚未膨胀并填充到其中RecyclerView。HomeFragment在开始转换之前,我们需要一种方法来等待我们列出我们的列表。
// 如果postponeEnterTransition被调用,任何要运行的进入转换将被保持,直到调用结束调用startPostponedEnterTransition。这使我们有机会“安排”我们的转换,直到RecyclerView用电子邮件填充并且转换能够找到您配置的映射之后。
postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }
//进入方法就设置(这是上面所说嵌套的原因)
//谷歌是在上面的列表布局监听中(即实现跳转的监听)设置
//设置进出动画,避免列表跳转到详情页除了该列表其他部分白屏的情况
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()
}
//...
}
接下来,为了确保将MaterialElevationScale过渡作为一个整体应用于主屏幕,而不是应用于层次结构中的每个单独视图,将RecyclerViewin标记fragment_tab_in_rest_rest.xml为过渡组。
以及根布局碎片也要设置
注意我这里由于根部局有backdrop,会出现同时加载背层布局所以给所在的最外层RestFragment也设置了
谷歌原代码是没有显示的
可能出现的报错 参考原因
设置监听的实际是listitem所对应的根元素而不是listitem中设置了transition_name属性所在的布局
应该改为:
init {
binding.cvListitemRoot.setOnClickListener {
selectIndex = pos
binding.rvCompositionAdapterListener?.RvItemOnclick(it)
}
}



