Fragment调用addSharedElement()过渡首次闪烁问题求助
解决Fragment间共享元素过渡首次闪烁问题
我之前也碰到过一模一样的场景!Fragment A到Fragment B的共享元素过渡首次执行时会闪烁,但后续完全正常,这个问题大多和Fragment生命周期、视图初始化时机或者过渡配置有关。给你几个经过实战验证的修复方案:
方案1:在Fragment事务中启用重排序优化
这是最容易尝试的方案,API 24+可用,它能让FragmentManager优化事务执行顺序,确保过渡开始前目标视图已经完成初始化:
fragmentManager!!.beginTransaction() .setReorderingAllowed(true) // 关键添加这一行 .addSharedElement(viewHolder.characterImage, ViewCompat.getTransitionName(viewHolder.characterImage)) .addToBackStack(TAG) .replace(R.id.fragmentContent, CharacterFragment.newInstance(url, viewHolder.characterName.text.toString())) .commit()
setReorderingAllowed(true)会调整事务的执行步骤,优先处理目标Fragment的视图创建与测量,避免过渡开始时视图处于未就绪状态导致闪烁。
方案2:确保目标Fragment的视图与资源准备就绪后再启动过渡
首次闪烁的常见原因是Fragment B的ImageView还没加载好对应图片,过渡开始时显示空白或占位图。你可以在Fragment B的onViewCreated方法中设置过渡,并监听过渡状态,确保图片加载完成:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { sharedElementEnterTransition = TransitionInflater.from(requireContext()) .inflateTransition(android.R.transition.move) // 添加过渡监听,确保图片加载完成再执行过渡 sharedElementEnterTransition?.addListener(object : Transition.TransitionListener { override fun onTransitionStart(transition: Transition) { val targetImg = view.findViewById<ImageView>(R.id.characterImage) // 如果使用Glide/Picasso加载图片,这里要确保图片已加载完成 // 示例(Glide): // Glide.with(this) // .load(yourImageUrl) // .listener(object : RequestListener<Drawable> { // override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean { // transition.resume() // return false // } // override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { // transition.resume() // return false // } // }) // .into(targetImg) // transition.pause() // 先暂停过渡,等图片加载完成再恢复 } override fun onTransitionEnd(transition: Transition) { transition.removeListener(this) // 移除监听避免内存泄漏 } override fun onTransitionCancel(transition: Transition) { transition.removeListener(this) } override fun onTransitionPause(transition: Transition) {} override fun onTransitionResume(transition: Transition) {} }) } }
方案3:禁用默认的进入/退出过渡,避免冲突
有时候Fragment的默认进入过渡会和共享元素过渡叠加执行,导致视觉闪烁。你可以在Fragment B的onCreate中禁用默认过渡:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { enterTransition = null // 禁用默认进入过渡 exitTransition = null // 禁用默认退出过渡 } }
建议先尝试方案1,大多数情况下这个简单的配置就能解决问题。如果还是存在闪烁,再结合方案2确保图片资源就绪,或者方案3消除过渡冲突。
内容的提问来源于stack exchange,提问作者Ruslan Leshchenko
相关产品推荐
相关产品推荐

