GridLayout内CardView的Shared Element Transition无法生效问题排查
问题分析与修复方案
核心问题
你的共享元素过渡失效是以下几个关键错误导致:
1. 共享元素TransitionName不匹配
源CardView设置的TransitionName是it.id.toString()(比如first、second),但目标CardView设置的是固定值scale_transition,系统无法识别这是同一组共享元素,自然不会触发过渡动画。
2. 过渡资源加载错误
GameSelectionFragment中加载过渡文件时多了.xml后缀,导致资源找不到:
// 错误写法 inflateTransition(R.transition.scale_transition.xml) // 正确写法 inflateTransition(R.transition.scale_transition)
3. 不必要的过渡延迟
你的目标CardView没有异步加载内容(比如图片),不需要调用postponeEnterTransition,过早触发startPostponedEnterTransition反而可能导致过渡异常。
修复后的代码示例
修改AppsFragment.kt
确保源CardView和目标CardView使用相同的TransitionName,通过Bundle将名称传递给目标Fragment:
override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { binding = FragmentAppsBinding.inflate(layoutInflater) val view = binding.root binding.appsGridLayout.forEach { cardView -> val transitionName = cardView.id.toString() ViewCompat.setTransitionName(cardView as CardView, transitionName) cardView.setOnClickListener { parentFragmentManager.commit { val newFragment = GameSelectionFragment().apply { arguments = Bundle().apply { putString("TRANSITION_NAME", transitionName) } } setReorderingAllowed(true) addSharedElement(cardView, transitionName) replace(R.id.appFragment, newFragment) addToBackStack(null) } } } return view }
修改GameSelectionFragment.kt
修正过渡资源加载,接收传递的TransitionName并设置给目标CardView:
class GameSelectionFragment : Fragment() { private lateinit var binding: FragmentGameSelectionBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 修正资源加载路径 sharedElementEnterTransition = TransitionInflater.from(requireContext()) .inflateTransition(R.transition.scale_transition) // 设置返回过渡,保证返回时的动画一致性 sharedElementReturnTransition = TransitionInflater.from(requireContext()) .inflateTransition(R.transition.scale_transition) } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { binding = FragmentGameSelectionBinding.inflate(layoutInflater) val view = binding.root // 获取传递的TransitionName并设置 arguments?.getString("TRANSITION_NAME")?.let { ViewCompat.setTransitionName(binding.appCard, it) } return view } }
scale_transition.xml(无需修改)
你的过渡配置是正确的:
<?xml version="1.0" encoding="utf-8"?> <transitionSet xmlns:android="http://schemas.android.com/apk/res/android" android:duration="300"> <changeBounds/> <changeTransform/> </transitionSet>
额外注意事项
- 确保Activity主题开启窗口内容过渡,在
styles.xml中添加:<item name="android:windowContentTransitions">true</item> - 移除布局中
android:animateLayoutChanges="true"属性,该属性可能和共享元素过渡冲突。
内容的提问来源于stack exchange,提问作者Shaveen
相关产品推荐
相关产品推荐

