无内容变更时TransitionListener回调未触发问题咨询
解决ConstraintSet无变化时TransitionListener不回调的问题
哥们,你碰到的这个问题我之前也踩过坑——当ConstraintSet和当前布局完全一致的时候,TransitionManager会直接跳过动画流程,连带着你的TransitionListener回调也不会触发,确实挺闹心的。下面给你两个靠谱的解决思路:
思路1:提前判断布局差异,按需执行逻辑
这是最推荐的方案,先检查ConstraintSet和当前布局有没有差异,没差异就直接执行你原本要在onTransitionEnd里做的操作,不用走动画流程:
val transition = AutoTransition() transition.addListener(object : Transition.TransitionListener { override fun onTransitionEnd(transition: Transition) { // 原本要执行的结束操作 doSomething() } // 其他回调可以用空实现,嫌麻烦的话可以换成TransitionAdapter简化代码 override fun onTransitionStart(transition: Transition) {} override fun onTransitionCancel(transition: Transition) {} override fun onTransitionPause(transition: Transition) {} override fun onTransitionResume(transition: Transition) {} }) val constraintSet = ConstraintSet() constraintSet.clone(this, R.layout.frame_loading) // 关键:用matches()判断是否有布局变化 if (constraintSet.matches(rootLayout)) { // 没有布局变更,直接执行结束逻辑 doSomething() } else { // 有变化才启动动画 TransitionManager.beginDelayedTransition(rootLayout, transition) constraintSet.applyTo(rootLayout) }
思路2:强制触发Transition回调(hack式)
如果不管有没有布局变化,你都必须触发Transition的回调,可以给Transition添加一个空的过渡动画,确保系统认为有动画需要执行:
// 自定义一个包含空动画的TransitionSet,强制触发回调 val forcedTransition = TransitionSet() .addTransition(AutoTransition()) .addTransition(object : Transition() { override fun captureStartValues(sceneValues: TransitionValues) {} override fun captureEndValues(sceneValues: TransitionValues) {} override fun createAnimator(sceneRoot: ViewGroup, startValues: TransitionValues?, endValues: TransitionValues?): Animator? { // 返回一个时长为0的空动画,确保流程走通 return ValueAnimator.ofFloat(0f, 1f).apply { duration = 0 } } }) forcedTransition.addListener(object : Transition.TransitionListener { override fun onTransitionEnd(transition: Transition) { doSomething() } // 其他空实现... override fun onTransitionStart(transition: Transition) {} override fun onTransitionCancel(transition: Transition) {} override fun onTransitionPause(transition: Transition) {} override fun onTransitionResume(transition: Transition) {} }) val constraintSet = ConstraintSet() constraintSet.clone(this, R.layout.frame_loading) TransitionManager.beginDelayedTransition(rootLayout, forcedTransition) constraintSet.applyTo(rootLayout)
小提示
- 思路1更高效,避免了不必要的动画开销,优先用这个;
- 思路2适合一些特殊场景,但会多走一次空动画的流程,性能上略逊一筹。
内容的提问来源于stack exchange,提问作者Longi
相关产品推荐
相关产品推荐

