Lottie animation disappears on last TabView page in SwiftUI

805 views Asked by At

I have a TabView with six pages. The animation is in the last page.

When I attend to the last page the animation shows for a split second and disappear completely. Thought it might be problem with the animation but it works elsewhere just fine.

I present this TabView using sheet.

Last page:

struct SixScreen: View{
    
    @EnvironmentObject var session: SessionStore
    
    @Binding var dismiss: Bool
    
    var body: some View{
        VStack(spacing: 16){
            Spacer()
            LottieView(name: "complete")
                .frame(width: 200, height: 200, alignment: .center)
            Button(action: {
                dismiss.toggle()
            }, label: {
                Text("Start")
                    .frame(width: 100, height: 50, alignment: .center)
                    .foregroundColor(.blue)
                    .background(Color.white)
                    .cornerRadius(10)
                    .shadow(color: .blue, radius: 5, x: 0, y: 1)
            })
            .padding(.bottom, 32)
            Spacer()
        }
    }
}

Lottie View implementation:

struct LottieView: UIViewRepresentable {
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    var name: String!
    var animationView = AnimationView()

    class Coordinator: NSObject {
        var parent: LottieView
    
        init(_ animationView: LottieView) {
            self.parent = animationView
            super.init()
        }
    }

    func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
        let view = UIView()

        animationView.animation = Animation.named(name)
        animationView.contentMode = .scaleAspectFit
        animationView.loopMode = .loop
        
        animationView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(animationView)

        NSLayoutConstraint.activate([
            animationView.widthAnchor.constraint(equalTo: view.widthAnchor),
            animationView.heightAnchor.constraint(equalTo: view.heightAnchor)
        ])

        return view
    }

    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<LottieView>) {
        animationView.play()
    }
}

Tab View:

Group{
            TabView{
                FirstScreen()
                SecondScreen()
                ThirdScreen()
                FourthScreen()
                FifthScreen()
                SixScreen(dismiss: $dismiss)
            }
            .tabViewStyle(PageTabViewStyle())
            .indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
            .padding(.bottom)
        }
        .background(gradient)
        .edgesIgnoringSafeArea(.all)
        .navigationBarHidden(true)
}
2

There are 2 answers

0
Sergei Volkov On

Try to force refresh the view using the .id() modifier

struct AnimationView: View {
    
    @State private var lottieID = UUID()
    
    var body: some View {
        LottieView(name: "complete")
            .frame(width: 200, height: 200, alignment: .center)
            .id(lottieID)
            .onAppear {
                lottieID = UUID()
            }
    }
}
0
Piero Sifuentes On

After a lot of research and testing, if you're looking to keep the Lottie animation live inside the SwiftUI TabView you should add this code snippet:

 public func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
    let view = UIView(frame: .zero)
    let animation = Animation.named(lottieFile)
    animationView.animation = animation
    animationView.animationSpeed = animationSpeed
    animationView.contentMode = .scaleAspectFit
    animationView.loopMode = loopMode
    animationView.backgroundBehavior = .pauseAndRestore <------