问题描述
我想在具有两个共享元素的片段之间进行转换。但问题是:只有一个动画。
共享元素取自第一个片段中列表中的 viewHolder。我使用的过渡来自材料库,正是这些https://medium.com/androiddevelopers/material-motion-with-mdc-c1f09bb90bf9
片段 A:
fragmentManager.commit {
replace([...])
setReorderingallowed(true)
addSharedElement(viewA,viewA.transitionName)
addSharedElement(viewB,viewB.transitionName)
addToBackStack(fragmentClass.qualifiedname)
}
片段 B:
sharedElementReturnTransition = MaterialContainerTransform().apply {
scrimColor = Color.TRANSPARENT
duration = 3000L
interpolator = DecelerateInterpolator()
}
binding.headerContainer.header.cover.transitionName = arguments?.getString("firstTrName") ?: return
binding.headerContainer.title.cover.transitionName = arguments?.getString("secondTrName") ?: return
binding.headerContainer.header.setimageResource(arguments?.getString("image") ?: return)
binding.headerContainer.title.text = arguments?.getString("title") ?: return
似乎只有我在 commit{} 中添加的最后一个元素是过渡元素。我已经检查了所有内容,转换名称是唯一的,所有数据都在第二个片段中,所有转换名称,这不是参数问题。有任何想法吗?非常感谢您的帮助,这是一个非常重要的客户请求。
解决方法
https://material.io/develop/android/theming/motion
与传统的 Android 共享元素不同,它不是围绕 要移动的单个共享内容(例如图像) 两个场景之间。相反,这里的共享元素指的是 起始视图或视图组的边界容器(例如整行 列表中项目的布局)将其大小和形状转换为 结束视图或视图组(例如全屏的根视图组 分段)。这些开始和结束容器视图是“共享的 元素”的容器变换。当这些容器被 转换后,它们的内容被交换以创建过渡。
两个共享元素无法正常工作。当从列表顶部选择开始视图时,imageView 成为一个容器。从底部选择时,textView 成为一个容器。 (从下面的 gif 中查看 example1 和 example5 之间的区别)
您可以使用传统的共享元素过渡代替 Material Motion。
示例和 GIF
fragmentEnd.sharedElementEnterTransition = MaterialContainerTransform().apply {
scrimColor = Color.TRANSPARENT
containerColor = Color.TRANSPARENT
duration = 1000L
interpolator = DecelerateInterpolator()
}
fragmentEnd.sharedElementReturnTransition = MaterialContainerTransform().apply {
scrimColor = Color.TRANSPARENT
containerColor = Color.TRANSPARENT
duration = 1000L
isElevationShadowEnabled = false
interpolator = DecelerateInterpolator()
}
val manager: FragmentManager = activity.supportFragmentManager
manager.beginTransaction()
.setReorderingAllowed(true)
.addSharedElement(imageView,imageView.transitionName)
.addSharedElement(textView,textView.transitionName)
.addToBackStack(null)
.replace([...])
.commit()
解决方案
您可以像这样更改过渡:
fragmentEnd.sharedElementEnterTransition = getTransition()
fragmentEnd.sharedElementReturnTransition = getTransition()
private fun getTransition(): Transition{
val set = TransitionSet()
set.ordering = TransitionSet.ORDERING_TOGETHER
set.addTransition(ChangeBounds())
set.addTransition(ChangeImageTransform())
set.addTransition(ChangeTransform())
return set
}
使用 MaterialContainerTransform 的正确方法:
-
分享一个元素
fragmentEnd.sharedElementEnterTransition = MaterialContainerTransform().apply { scrimColor = Color.TRANSPARENT containerColor = ResourcesCompat.getColor(activity.resources,R.color.purple_amethyst,null) duration = 1000L startShapeAppearanceModel = ShapeAppearanceModel().withCornerSize(100f) interpolator = DecelerateInterpolator() } fragmentEnd.sharedElementReturnTransition = MaterialContainerTransform().apply { scrimColor = Color.TRANSPARENT containerColor = ResourcesCompat.getColor(activity.resources,null) duration = 1000L endShapeAppearanceModel = ShapeAppearanceModel().withCornerSize(100f) interpolator = DecelerateInterpolator() } val manager: FragmentManager = activity.supportFragmentManager manager.beginTransaction() .setReorderingAllowed(true) .addSharedElement(imageView,imageView.transitionName) .addToBackStack(null) .replace([...]) .commit()
-
FragmentEnd 布局:
<androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/container" android:background="@color/purple_amethyst"> <....../> </androidx.constraintlayout.widget.ConstraintLayout>
-
将过渡名称设置为 fragmentEnd 的顶部布局
ViewCompat.setTransitionName(binding.container,getArguments().getString("imageViewTransitionName"));
结果