返回

动画在 Fragment onPause 时未触发 onAnimationEnd 的问题及解决之道

Android

## 动画在 Fragment onPause 时未触发 onAnimationEnd 的问题及解决方案

当动画在 Fragment 中设置时,它在 Fragment 的 onPause 生命周期方法被调用时可能会停止,导致 onAnimationEnd 回调不会被触发。这个问题的根源在于动画系统在非活动状态时会暂停,包括当 Fragment 暂停时。

要解决这个问题,我们可以采取几种方法:

### 1. 使用 ViewPropertyAnimator

ViewPropertyAnimator 是一个针对 View 属性设置动画的强大类。与传统动画不同,它具有在 View 处于非活动状态时继续动画的能力。

viewBinding.img.animate()
    .rotation(degree)
    .duration(animationDuration)
    .withEndAction {
        onAnimationEnd()
    }

### 2. 使用自定义动画监听器

我们可以创建一个自定义动画监听器,该监听器将在 Fragment 重新获得焦点时继续动画。

val rotate = RotateAnimation(
    degreeOld, degree,
    RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f).also {
    it.duration = animationDuration
    it.fillAfter = true
    it.repeatCount = repeatCount
    it.setAnimationListener(object : Animation.AnimationListener {
        override fun onAnimationStart(animation: Animation) {}
        override fun onAnimationRepeat(animation: Animation) {}
        override fun onAnimationEnd(animation: Animation) {
            onAnimationEnd()
        }
    })
}

override fun onResume() {
    super.onResume()
    viewBinding.img.startAnimation(rotate)
}

### 3. 在 Fragment 恢复时重新启动动画

当 Fragment 恢复时,我们可以手动重新启动动画。

override fun onResume() {
    super.onResume()
    val rotate = RotateAnimation(
        degreeOld, degree,
        RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f).also {
        it.duration = animationDuration
        it.fillAfter = true
        it.repeatCount = repeatCount
    }
    viewBinding.img.startAnimation(rotate)
}

### 结论

为了获得最佳效果,建议使用 ViewPropertyAnimator,因为它提供了对动画的更精细控制和灵活性。

### 常见问题解答

Q1:为什么动画在 Fragment onPause 时会停止?
A1:当 Fragment 处于非活动状态时,动画系统会暂停,导致动画停止播放。

Q2:ViewPropertyAnimator 与传统动画有何不同?
A2:ViewPropertyAnimator 可以在 View 处于非活动状态时继续动画,而传统动画则会暂停。

Q3:自定义动画监听器如何工作?
A3:自定义动画监听器允许我们在 Fragment 重新获得焦点时继续动画,即使动画之前已暂停。

Q4:为什么在 Fragment 恢复时重新启动动画是有效的?
A4:在 Fragment 恢复时重新启动动画可以确保动画在 Fragment 处于活动状态时从头开始播放。

Q5:哪种方法最适合我的用例?
A5:最佳方法取决于具体用例。对于需要在非活动状态时继续动画的情况,建议使用 ViewPropertyAnimator。