我有一个具有Instagram故事等功能的应用程序。我有5条以1乘1的条形填充以指示电影的长度。当视频再次开始播放时,这也可以正常工作,重设小节。

android - 在onAnimationEnd中调用ValueAnimator时不会将其取消-LMLPHP

但是,当我切换到下一个视频并且与上一个视频一起位于bar3中时,bar0开始(如预期的那样),但是bar4也开始。切换到新视频会触发onAnimationEnd,我希望取消动画,以便重新加载新的进度指示。 cancel()end()removeListener(this),它们都不起作用。

    fun startAnimation(duration: Long, progressBars: ArrayList<ProgressBar>, currentBar: Int) {
        Timber.d("test currentBar = $currentBar")
        if (currentBar == 0) {
            for (bar in progressBars) {
                bar.setProgress(0)
            }
        }
        animator?.end()
        animator?.cancel()
        animator?.removeAllListeners()
        animator = null

        animator = ValueAnimator.ofInt(0, progressBars[currentBar].getMax())

        animator?.duration = duration
        animator?.addUpdateListener { animation ->
            progressBars[currentBar].setProgress(animation.animatedValue as Int)
        }
        animator?.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator) {
                super.onAnimationEnd(animation)
//              animation.removeListener(this)
                animation.cancel()
                animation.end()

                var nextBar = currentBar + 1
                if (nextBar == progressBars.size) {
                    nextBar = 0
                }
                Timber.d("test nextBar = $nextBar")
                startAnimation(duration, progressBars, nextBar)
            }
        })
        animator?.start()
    }

最佳答案

第一件事是; cancel()end()方法实际上是在调用onAnimationEnd()方法。因此,在onAnimationEnd()方法内部调用它们没有帮助。

您应该有一种停止已经开始的动画系列的方法。因为由于递归,它将继续开始下一个动画。

这是我们想要的代码(或更漂亮的东西);

lateinit currentViewBarAnimation: CancelableAnimation
fun onCreate(){
    currentViewBarAnimation = startAnimation(duration, progressBars, 0)
}

fun onNextVideoStarted(){
    currentViewBarAnimation.stopOrCancelOrWhateverYouNameIt()
    currentViewBarAnimation = startAnimation(duration, progressBars, 0)
}

CancellableAnimation可以是仅具有 bool(boolean) 值的类。
class CancelableAnimation(private var cancelled: Boolean = false){
    fun cancel(){
      cancelled = true
    }

    fun isCancelled() = cancelled
}

现在是最后的接触;
fun startAnimation(duration: Long, progressBars: ArrayList<ProgressBar>, currentBar: Int) : CancellableAnimation{
        Timber.d("test currentBar = $currentBar")
        if (currentBar == 0) {
            for (bar in progressBars) {
                bar.setProgress(0)
            }
        }
        animator?.end()
        animator?.cancel()
        animator?.removeAllListeners()

        animator = ValueAnimator.ofInt(0, progressBars[currentBar].getMax())

        animator?.duration = duration
        animator?.addUpdateListener { animation ->
            progressBars[currentBar].setProgress(animation.animatedValue as Int)
        }


        val cancellableAnimation = CancellableAnimation()
        animator?.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator) {
                super.onAnimationEnd(animation)

                if(cancellableAnimation.isCancelled()) return
                var nextBar = currentBar + 1
                if (nextBar == progressBars.size) {
                    nextBar = 0
                }
                Timber.d("test nextBar = $nextBar")
                startAnimation(duration, progressBars, nextBar)
            }
        })
        animator?.start()

        return cancellableAnimation
    }

看起来有些混乱,但这是必须采取的措施,因为移至新视频是一种异步操作。

10-07 17:58