Home > Mobile >  Multiple Lottie animations fire at a same time
Multiple Lottie animations fire at a same time

Time:10-27

I have my LottieView

struct LottieView: UIViewRepresentable {
    var name: String
    var loopMode: LottieLoopMode = .loop
    var contentMode: UIView.ContentMode = .scaleAspectFit
    var paused: Bool = false
    var shouldPlay: Bool = true
    
    var animationView = AnimationView()
    
    func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
        let view = UIView(frame: .zero)
        
        animationView.animation = Animation.named(name)
        animationView.contentMode = contentMode
        animationView.loopMode = loopMode
        animationView.backgroundBehavior = .pauseAndRestore
        if shouldPlay {
            animationView.play()
        }
        
        animationView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(animationView)
        
        NSLayoutConstraint.activate([
            animationView.heightAnchor.constraint(equalTo: view.heightAnchor),
            animationView.widthAnchor.constraint(equalTo: view.widthAnchor)
        ])
        
        return view
    }
    
    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<LottieView>) {
        if shouldPlay {
            context.coordinator.parent.animationView.play { finished in
                if context.coordinator.parent.animationView.loopMode == .playOnce && finished {
                    context.coordinator.parent.animationView.play()
                    DispatchQueue.main.asyncAfter(deadline: .now()   0.3) {
                        context.coordinator.parent.animationView.pause()
                    }
                }
            }
        } else {
            context.coordinator.parent.animationView.pause()
        }
    }
    
    func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }

    class Coordinator: NSObject {
        var parent: LottieView

        init(_ parent: LottieView) {
            self.parent = parent
        }
    }
}

which animation's start depends on it's property shouldPlay passed in view's initializer.

I use LottieView in custom AddToCartButton structure:


struct AddToCartButton: View {
    let onAdd: () -> Void
    
    @State private var shouldPresentAddAnimation: Bool = false
    
    var body: some View {
        Button {
            withAnimation {
                shouldPresentAddAnimation = true
                onAdd()
            }
        } label: {
            HStack(spacing: 0) {
                LottieView(name: "add_to_cart_2",
                           loopMode: .playOnce,
                           contentMode: .scaleAspectFit,
                           shouldPlay: shouldPresentAddAnimation)
                .frame(minWidth: 50, maxHeight: 40)
                
                Text("Add to Cart")
                    .font(.ssButton)
                    .foregroundColor(.ssWhite)
                    .padding(.all, 10)
            }
            .padding(.vertical, 5)
            .background {
                RoundedRectangle(cornerRadius: 5)
            }
            .fixedSize(horizontal: true, vertical: false)
        }
    }
}

Clicking on this button should play the animation once and then return to initial animation state thanks to the code in LottieView's updateUIView method.

I have my main view in which there are many AddToCartButton structures created like this:

AddToCartButton {
    [some code...]
}

And the effect is that at first button click, it animates properly. On second different button click the second and the first one animation fires. When clicking on third button, all three buttons fire animations. Sample in the photos attached:

Firstly, the initial state of buttons: enter image description here

Secondly, after one button click: enter image description here

Finally, after second button click (two of them fire animation): enter image description here

What I want is that only the button that is clicked fire it's animation.

CodePudding user response:

I think the problem is that you don’t set shouldPresentAddAnimation back to false after animation is played. So every time you press the button the whole list is rendered and since you state property is true, it fires animation.

  • Related