Fragment触发onPause时onAnimationEnd未被调用的问题求解
解决AnimationListener的onAnimationEnd在Fragment切换时不触发的问题
核心原因
切换Fragment时,原Fragment的View会被从Window中移除(或进入不可见状态),系统会自动取消绑定在该View上的Animation,导致onAnimationEnd不会被调用。Handler或Coroutine仅负责线程切换,无法改变系统对View动画的生命周期管理逻辑。
具体解决方案
1. 关联Fragment视图生命周期,主动处理动画状态
在Fragment中利用viewLifecycleOwner的生命周期回调,在View暂停/销毁时手动控制动画状态,避免逻辑丢失:
private var animation: Animation? = null private var isAnimationRunning = false override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) animation = AlphaAnimation(1f, 0f).apply { duration = 1000 setAnimationListener(object : Animation.AnimationListener { override fun onAnimationEnd(animation: Animation) { isAnimationRunning = false Log.d("TAG", "onAnimationEnd") // 执行你的结束逻辑 } override fun onAnimationStart(animation: Animation) { isAnimationRunning = true } override fun onAnimationRepeat(animation: Animation) {} }) } } override fun onPause() { super.onPause() animation?.let { if (it.hasStarted() && !it.hasEnded()) { it.cancel() // 可选:直接触发结束逻辑,避免任务遗漏 // onAnimationEnd(it) } } } override fun onResume() { super.onResume() if (isAnimationRunning) { view.startAnimation(animation) } }
2. 改用ViewPropertyAnimator替代传统Animation
ViewPropertyAnimator的生命周期感知更贴合View状态,doOnEnd回调不受Fragment直接切换影响(只要View未被销毁):
view.animate() .alpha(0f) .setDuration(1000) .doOnEnd { Log.d("TAG", "Animation ended") // 执行你的结束逻辑 } .start()
3. 将动画结束逻辑与视图解耦,迁移至ViewModel
如果动画结束后的操作不依赖当前Fragment的View,可以把逻辑放到ViewModel中,通过LiveData通知Fragment执行UI操作:
// ViewModel类 class MyViewModel : ViewModel() { private val _animationEnded = MutableLiveData<Boolean>() val animationEnded: LiveData<Boolean> = _animationEnded fun triggerAnimationEnd() { _animationEnded.postValue(true) } } // Fragment中 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val viewModel = ViewModelProvider(this)[MyViewModel::class.java] view.animate() .alpha(0f) .setDuration(1000) .doOnEnd { viewModel.triggerAnimationEnd() } .start() viewModel.animationEnded.observe(viewLifecycleOwner) { Log.d("TAG", "onAnimationEnd from ViewModel") // 执行动画结束后的UI逻辑 } }
4. 手动计算动画进度,确保逻辑执行
如果必须保证结束逻辑执行,可在启动动画时记录时间点,在Fragment生命周期变化时判断是否触发逻辑:
private var animationStartTime: Long = 0 private val animationDuration = 1000L private fun startAnimation() { animationStartTime = System.currentTimeMillis() val animation = AlphaAnimation(1f, 0f).apply { duration = animationDuration.toInt() setAnimationListener(object : Animation.AnimationListener { override fun onAnimationEnd(animation: Animation) { handleAnimationEnd() } override fun onAnimationStart(animation: Animation) {} override fun onAnimationRepeat(animation: Animation) {} }) } view.startAnimation(animation) } override fun onPause() { super.onPause() val elapsedTime = System.currentTimeMillis() - animationStartTime // 动画已执行足够时长,直接触发结束逻辑 if (elapsedTime >= animationDuration) { handleAnimationEnd() } } private fun handleAnimationEnd() { Log.d("TAG", "onAnimationEnd") // 你的结束逻辑 }
内容的提问来源于stack exchange,提问作者GHH
相关产品推荐
相关产品推荐

