【问题标题】:SwiftUI playing Lottie animationSwiftUI 播放 Lottie 动画
【发布时间】:2020-10-24 22:20:34
【问题描述】:

这些天我一直在玩 Lottie 动画,但我在如何阻止它们离开视图时遇到了一些麻烦。

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

【问题讨论】:

    标签: swift animation swiftui lottie


    【解决方案1】:

    你几乎得到它。您需要构造一个Coordinator,以便您可以访问LottieView 中的值。这样做很简单。

    1. 创建一个符合NSObjectCoordinator
    2. 请输入您的LottieView
    3. 将函数makeCoordinator 添加到您的LottieView
    4. makeCoordinator 函数中创建Coordinator 的实例
    5. 在您的updateUIView 中,从coordinator 访问animationView

    您不需要绑定isAnimating,因为LottieView 不会将任何信息传递回您的ContentView。对于name,您也不需要@State

    以下是我如何让 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")
                })
            }
    
        }
    }
    

    它正在工作:

    【讨论】:

    • 嘿,一个问题。你知道如何在视图加载之前播放它吗?因为我正在从服务器获取数据,并且我想在数据加载时播放动画。现在它只在视图完全加载到屏幕上时启动。谢谢老哥!
    • 这真的取决于你如何呈现加载屏幕。理想情况下,您应该有一些状态变量来确定屏幕的状态(主要状态通常是加载、加载、错误)。根据您的设置,您如何处理这些状态并根据这些状态呈现视图可能非常复杂或微不足道。我认为不可能在评论中很好地回答您的问题。
    • 非常感谢。您是否有任何项目示例?
    • 一个简短的附录:如果你 - 像我一样 - 不要循环你的动画而只播放一次并且希望它在下次单击按钮时再次播放,我调整了 updateUIView "else"部分到:context.coordinator.parent.animationView.play { (_) in context.coordinator.parent.isPaused = true } 所以动画播放完后它会再次自动暂停。 :)
    • 非常感谢,在 Lottie 上的 UIRepresentable 更简单的仅播放版本不适用于播放/暂停。
    猜你喜欢
    • 1970-01-01
    • 2022-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多