Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AnimatedSwitch behaves differently with coreAnimationEngine vs mainThreadEngine #1877

Closed
nevil opened this issue Dec 22, 2022 · 1 comment · Fixed by #1897
Closed

AnimatedSwitch behaves differently with coreAnimationEngine vs mainThreadEngine #1877

nevil opened this issue Dec 22, 2022 · 1 comment · Fixed by #1897
Labels

Comments

@nevil
Copy link
Contributor

nevil commented Dec 22, 2022

Which Version of Lottie are you using?

Latest commit 3b90792

Description

We are using an AnimatedSwitch with the default settings for the progress for each state.
We do not call setProgressForState(...)

  fileprivate var onStartProgress: CGFloat = 0
  fileprivate var onEndProgress: CGFloat = 1
  fileprivate var offStartProgress: CGFloat = 1
  fileprivate var offEndProgress: CGFloat = 0

When animating back from on to off state the animation does not behave as expected.
I believe the root cause is that currentFrame is 0 at this point for the coreAnimationEngine but not for the mainThreadEngine.

Because of that, in addNewAnimationForContext(...) the playFrom value will be forced to 0:

        switch loopMode {
        // When playing exactly once (and not looping), we can just set the
        // `playFrom` time to be the `currentFrame`. Since the animation duration
        // is based on `playFrom` and `playTo`, this automatically truncates the
        // duration (so the animation stops playing at `playFrom`).
        case .playOnce:
          animationContext.playFrom = currentFrame

With the mainThreadEngine the currentFrame will be set to the expected value in didAnimationStop but this is not the case for the coreAnimationEngine.

    if let animationLayer = animationLayer, let key = animationKey {
      animationLayer.removeAnimation(forKey: key)
      if flag {
        animationLayer.currentFrame = (anim as! CABasicAnimation).toValue as! CGFloat
      }
    }

Temporary workaround, not sure if it is accurate :-)
Force setting the currentProgress also for coreAnimationEngine

-        // For the Main Thread rendering engine, we freeze the animation at the expected final progress
-        // once the animation is complete. This isn't necessary on the Core Animation engine.
-        if finished, !(self.animationView.animationLayer is CoreAnimationLayer) {
+       if finished {
            self.animationView.currentProgress = finalProgress
        }

Expected Behavior

Screen.Recording.2022-12-22.at.18.16.51.mp4

Actual Behavior

Screen.Recording.2022-12-22.at.18.17.23.mp4

Animation JSON

myListButton.json.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants