将 Android Lottie 动画与滚动对齐

Align Android Lottie animation to scrolling

我想使我的 Lottie 动画进度与 RecyclerView 或 ViewPager 的滚动对齐。然而,Lottie 似乎只显示“真实”的帧,并没有在它们之间进行插值。当正常播放动画时,这不会发生,Lottie 会在帧之间进行插值。如果我滚动得非常慢,我可以看到我的 RecyclerView 滚动但 Lottie 不更新框架。这是我目前所做的:

recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {

    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        super.onScrolled(recyclerView, dx, dy)

        val offset = recyclerView.computeHorizontalScrollOffset()
        val extent = recyclerView.computeHorizontalScrollExtent()
        val range = recyclerView.computeHorizontalScrollRange()

        val percentage = offset.toFloat() / (range.toFloat() - extent.toFloat())

        lottieAnimationView.progress = percentage
    }
}

当我尝试在 ValueAnimator 中更新进度时出现同样的问题,例如:

val valueAnimator = ValueAnimator.ofFloat(0f, 1f)
valueAnimator.duration = 30000
valueAnimator.addUpdateListener { animation ->
    lottieAnimationView.progress = animation.animatedFraction
}
valueAnimator.start()

我不确定我是不是漏掉了什么,或者 Lottie 不支持这个。它似乎与 iOS 一起工作。

这是我的问题的示例视频。上面的动画是通过 playAnimation 完成的,下面的动画是通过 valueAnimatorsetProgress:

完成的

我正在使用 Lottie 2.7.0,但我也尝试使用旧版本,如 2.6.x。我也尝试了最新的测试版 Lottie 3.0.0-beta4,但也遇到了同样的问题。

该应用尚未迁移到 AndroidX。

更新答案

自版本 3.0.7 起,问题已修复 (GitHub Issue)。现在可以使用 setProgress(float) 并在帧之间进行插值。

旧答案

我最终得到了一个 hacky 解决方法。可以使用 ValueCallback 调整部分动画。如果动画是一个合成(因此它的图层有自己的时间轴),则可以自行调整时间范围。幸运的是,我的动画就是这种情况。

当“根层”被称为“根”时,使用上面的示例会导致以下代码:

val valueCallback = LottieValueCallback(1f)
lottieAnimationView.addValueCallback(KeyPath("root"), LottieProperty.TIME_REMAP, valueCallback)

val valueAnimator = ValueAnimator.ofFloat(0f, 3.14f)
valueAnimator.duration = 30000
valueAnimator.addUpdateListener { animation ->
    valueCallback.setValue(animation.animatedValue as Float)
}
valueAnimator.start()

边节点:

  • 带有TIME_REMAPValueCallback使用了秒的时间值,而不是进度或帧数!
  • 动画必须 运行 - 否则 valueCallback.setValue(..) 将没有效果(例如将其放入循环中)

我真心希望有人能提出比这个更好的解决方案!