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,R.color.purple_amethyst,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"));
结果