Search code examples
swiftuirive

How to find out if Rive animation finishes playing in SwiftUI


I created a simple Rive animation that I would like played when my app is opened. The question is - how do I programmatically find out when the Rive animation has finished playing, so I can show the main content of my app?

struct MainView: View {

    var openingAnimation = RiveViewModel(fileName: "opening_animation")

    var body: some View {
        // if openingAnimation.hasFinishedPlaying() { <-- is there some method that looks like this?
            openingAnimation.view()
        // } else {
        // show main content of app
        // }

    }

}

It's a very simple Rive animation (imagine a rectangle moving from top of bottom of the artboard), no fancy state machine logic or input variables.

Tried diving into the Rive docs but couldn't find anything that seems to clearly address this - though it should be a very simple use case.


Solution

  • The way i figured out how to do this was by creating a view model that subclasses RiveViewModel and then overrides one of the methods to publish when the animation is complete using Combine. (This answer assumes you are familiar with Combine)

    class OpeningAnimationViewModel: RiveViewModel {
    
    let animationComplete = PassthroughSubject<Bool, Never>()
    
        override func setView(_ view: RiveView) {
            super.setView(view)
            view.playerDelegate = self
            view.stateMachineDelegate = self
            animationComplete.send(false)
        }
    
        //This function is called when the animation is completed
        override func player(pausedWithModel riveModel: RiveModel?) {
            self.animationComplete.send(true)
        }
    }
    

    then in your Swift UI view:

    struct MainView: View {
    
        var openingAnimationVM: OpeningAnimationViewModel?
    
        var body: some View {
          openingAnimationVM?.view()
        }
    
    }
    

    When the animation is complete it will publish a boolean and you can execute whatever code you put in the listener :)