简体   繁体   English

将Android Lottie动画对齐以滚动

[英]Align Android Lottie animation to scrolling

I want to align my Lottie animation progress with the scrolling of a RecyclerView or ViewPager. 我想将我的Lottie动画进度与RecyclerView或ViewPager的滚动对齐。 However Lottie seems to only show the "real" Frames and doesn't interpolate between them. 但是,Lottie似乎仅显示“真实”框架,而不在它们之间进行插值。 When normally playing the animation this doesn't happen and Lottie interpolates between Frames. 在正常播放动画时,不会发生这种情况,Lottie会在帧之间进行插值。 If I scroll really slowly I can see that my RecyclerView scrolls but Lottie doesn't update frames. 如果滚动真的很慢,我可以看到RecyclerView滚动了,但是Lottie不会更新框架。 Here is what I currently do: 这是我目前正在做的事情:

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
    }
}

The same problem occurs when I try to update the progress within a ValueAnimator, eg: 当我尝试更新ValueAnimator中的进度时,会发生相同的问题,例如:

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

I'm not sure if I miss something or this isn't supported by Lottie. 我不确定我是否想念某些东西,或者Lottie不支持。 It seems to work with iOS though. 它似乎可以与iOS一起使用。

Here is a sample video of my problem. 这是我的问题的示例视频。 The top animation is just done via playAnimation , the lower one is done via valueAnimator and setProgress : 最上面的动画是通过playAnimation完成的,下面的动画是通过valueAnimatorsetProgress

破碎的抽奖动画

Updated answer 更新的答案

The issue is fixed ( Github Issue ) since version 3.0.7 . 3.0.7版以来,此问题已修复( Github Issue )。 It's now possible to use setProgress(float) and it interpolates between frames. 现在可以使用setProgress(float)并在帧之间进行插值。

Old answer 老答案

I've ended up with a hacky workaround. 我最终遇到了一个棘手的解决方法。 It's possible to adjust parts of the animation with a ValueCallback . 可以使用ValueCallback调整动画的ValueCallback If the animation is a Composition (so its layers have their own timelines) it's possible to adjust the timeframe itself. 如果动画是合成(因此其图层具有自己的时间轴),则可以调整时间范围本身。 Luckily that's the case for my animation. 幸运的是我的动画就是这种情况。

Using my example from above this leads to the following code, when the "Root-Layer" is called "root": 使用上面的示例,当“ Root-Layer”被称为“ root”时,这将导致以下代码:

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()

Sidenodes: Sidenodes:

  • The ValueCallback with a TIME_REMAP uses a time value in seconds , not a progress or frame number! ValueCallbackTIME_REMAP使用以为单位的时间值,而不是进步或帧数!
  • The animation must run - otherwise valueCallback.setValue(..) will have no effect (eg put it in a loop) 动画必须运行-否则valueCallback.setValue(..)将无效(例如,放入循环中)

I seriously hope someone will come up with a better solution than this one! 我非常希望有人会提出比这个更好的解决方案!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM