SwiftUI 播放 Lottie 动画

SwiftUI playing Lottie animation

这些天我一直在玩 Lottie 动画,但我在如何从 View 中停止它们时遇到了一些麻烦。

这是我的 ContentView,我正在其中播放动画。我有一个实时显示布尔值的按钮:

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)
}
} 

这是我的 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)
        
    }
}
}

我有一个绑定布尔,每当我点击按钮时,它必须将自己更改为真或假。换句话说,当我按下按钮时,我应该能够播放和停止它。但不知何故,这个布尔值不在结构之间共享,动画一直在播放。我是 swift UI 的新手,所以我认为我做错了什么,因此我将不胜感激。

Here you can see my animation

你快搞定了。您需要构造一个 Coordinator 以便您可以访问 LottieView 中的值。做起来很简单。

  1. 创建一个符合NSObject
  2. Coordinatorclass
  3. 传递你的LottieView
  4. 将函数 makeCoordinator 添加到您的 LottieView
  5. makeCoordinator 函数中创建 Coordinator 的实例
  6. 在您的 updateUIView 中从 coordinator 访问 animationView

You shouldn't need a binding for the isAnimating as the LottieView is not passing any information back to your ContentView. You also don't need that @State for the name

以下是我如何让 Lottie 在我的应用程序中播放和暂停。请注意,某些变量名称与您的不同,但足以让您到达所需位置。

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
        }
    }
}

我的 ContentView 如下所示:

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")
            })
        }

    }
}

它正在运行: