【问题标题】:How to enable action with Lottie Button animation in SwiftUI?如何在 SwiftUI 中使用 Lottie Button 动画启用操作?
【发布时间】:2020-07-07 18:08:24
【问题描述】:

我有一个简单的项目,它在点击按钮时运行 Lottie 动画。

struct ContentView: View {

@State var number = 0
@State var toogleValue : Bool = false

var body: some View {
    ZStack {
        Color.green.opacity(0.2)
        ZStack {
            LottieButton(filename: "17247-happy-flower")
               .frame(width: 200)
               .onTapGesture {
                    self.number += 1
            }
            Text("number = \(self.number)")
            .offset( y: 150)
        }
    }.edgesIgnoringSafeArea(.all)
}
}

我想要实现的是:每当用户点击按钮时,动画应该开始并且数字计数器应该增加 1。

现在发生了什么:计数器加 1,但动画没有播放。

我尝试了什么:当我评论 // onTapGesture {self.number += 1} 时,动画工作正常,但计数器不工作。

这是 Lottie 按钮:

  struct LottieButton: UIViewRepresentable {
/// Create a button.
let animationButton = AnimatedButton()
var filename = "LottieLogo2"

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

let animation = Animation.named(filename)
animationButton.animation = animation
animationButton.contentMode = .scaleAspectFit

animationButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(animationButton)

animationButton.clipsToBounds = false
   /// Set animation play ranges for touch states
animationButton.setPlayRange(fromMarker: "touchDownStart", toMarker: "touchDownEnd", event: .touchUpInside)
 //  animationButton.setPlayRange(fromMarker: "touchDownEnd", toMarker: "touchUpCancel", event: .touchUpOutside)
 //  animationButton.setPlayRange(fromMarker: "touchDownEnd", toMarker: "touchUpEnd", event: .touchUpInside)
                                 
NSLayoutConstraint.activate([
    animationButton.heightAnchor.constraint(equalTo: view.heightAnchor),
    animationButton.widthAnchor.constraint(equalTo: view.widthAnchor),
])

return view
}

func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<LottieButton>) {
         
}
}

我认为问题是由于视图的层次结构造成的,但我不确定。

【问题讨论】:

    标签: swift animation swiftui lottie


    【解决方案1】:

    您需要接受可以与UIViewRepresentable 一起使用的Coordinator

    通过拥有Coordinator 类,它允许您将目标添加到animationView。目标和 Objective-C 公开的函数只能添加到类中。这意味着您可以在点击动画时执行任何操作。

    对于我们的LottieButton 结构,我们传递两个参数filenameaction。该动作基本上是一个闭包,允许我们传递一段稍后将执行的代码。

    我们通过传递对我们正在创建的LottieButton 的引用来设置Coordinator,然后我们添加目标。这需要在调用super.init 之后添加,因为我们需要用户self

    import SwiftUI
    import Lottie
    
    struct LottieButton: UIViewRepresentable {
    
        typealias UIViewType = UIView
        let animationView = AnimatedButton()
        let filename: String
        let action: () -> Void
    
        func makeUIView(context: UIViewRepresentableContext<LottieButton>) -> UIView {
            let view = UIView()
    
            let animation = Animation.named(filename)
            animationView.animation = animation
            animationView.contentMode = .scaleAspectFit
    
            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<LottieButton>) {
    
        }
    
        func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }
    
    
        class Coordinator: NSObject {
            let parent: LottieButton
    
            init(_ parent: LottieButton) {
                self.parent = parent
                super.init()
                parent.animationView.addTarget(self, action: #selector(touchUpInside), for: .touchUpInside)
            }
    
            // this function can be called anything, but it is best to make the names clear
            @objc func touchUpInside() {
                parent.action()
            }
        }
    }
    

    这意味着我们可以在 ContentView 中执行以下操作。当我们点击按钮时,我们的 action 参数现在可以执行我们想要的任何操作。

    struct ContentView: View {
    
        @State private var tapped: Int = 0
    
        var body: some View {
            VStack {
                LottieButton(filename: "loading", action: {
                    print("tapped")
                    tapped += 1
                })
                .frame(width: 200, height: 200)
    
                Text("tapped count \(tapped)")
            }
        }
    }
    

    它正在工作:

    【讨论】:

    • 你有没有关于如何在获取数据时播放动画并在屏幕上加载数据时停止的示例教程?我仍在努力解决这个问题。
    猜你喜欢
    • 2021-10-01
    • 2018-12-21
    • 2021-12-27
    • 2020-10-24
    • 1970-01-01
    • 2021-03-28
    • 2020-04-10
    • 1970-01-01
    • 2020-10-16
    相关资源
    最近更新 更多