I was playing with the Lottie animations, these days, but I have some trouble how to stop them from the View.
Here is my ContentView, where I am playing the animation. I have one button which shows the boolean value in real-time:
struct ContentView: View {
@State var isShowing : Bool = true
var body: some View {
ZStack {
Color.green.opacity(0.3)
VStack {
VStack {
LottieDosi(isShowing: .constant(isShowing)){Text("")}
Button(action: {self.isShowing.toggle()}) {
Text("Button is \(String(isShowing))")
.padding(10)
.background(Color.white)
.cornerRadius(40)
}
}.padding(.horizontal, 30)
}
}.edgesIgnoringSafeArea(.all)
}
}
and here is my LottieView:
struct LottieView: UIViewRepresentable {
@Binding var isAnimating: Bool
@State var name : String
var loopMode: LottieLoopMode = .loop
var animationView = AnimationView()
func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
let view = UIView()
animationView.animation = Animation.named(name)
animationView.contentMode = .scaleAspectFill
animationView.loopMode = .loop
animationView.play()
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>) {
isAnimating ? animationView.play() : animationView.stop()
}
}
struct LottieDosi<Content>: View where Content: View {
@Binding var isShowing: Bool
var content: () -> Content
var body: some View {
VStack {
LottieView(isAnimating: .constant(isShowing), name: "13728-sticker-4")
.frame(width: 175, height: 175)
}
}
}
I have a binding bool which has to change itself either to true or false, whenever I tap on the button. In other words, when I press the button I should be able to play and stop it. But somehow, this boolean value is not shared between the structs and the animation is constantly playing. I am new to swift UI, so I assume I am doing something very wrong, therefore I will appreciate some help.
Here you can see my animation
You've almost got it. You need to construct a Coordinator
so that you can access the values inside your LottieView
. It's straight forward to do.
Coordinator
class that conforms to NSObject
LottieView
.makeCoordinator
to your LottieView
Coordinator
in the makeCoordinator
functionupdateUIView
access the animationView
from the coordinator
.You shouldn't need a binding for the
isAnimating
as theLottieView
is not passing any information back to yourContentView
. You also don't need that@State
for thename
Here is how I have gotten Lottie to play and pause in my apps. Note that some of the variable names are different to yours but it should be enough to get you to where you need to be.
import SwiftUI
import Lottie
struct LottieView: UIViewRepresentable {
typealias UIViewType = UIView
let filename: String
let animationView = AnimationView()
let isPaused: Bool
func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
let view = UIView(frame: .zero)
let animation = Animation.named(filename)
animationView.animation = animation
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>) {
if isPaused {
context.coordinator.parent.animationView.pause()
} else {
context.coordinator.parent.animationView.play()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject {
var parent: LottieView
init(_ parent: LottieView) {
self.parent = parent
}
}
}
My ContentView
looks like the following:
struct ContentView: View {
@State private var isPaused: Bool = true
var body: some View {
VStack {
LottieView(filename: "loading", isPaused: isPaused)
.frame(width: 200, height: 200)
Button(action: {
self.isPaused.toggle()
}, label: {
Text(isPaused ? "Play" : "Pause")
})
}
}
}
Here it is working:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With