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 的新手,所以我认为我做错了什么,因此我将不胜感激。
你快搞定了。您需要构造一个 Coordinator
以便您可以访问 LottieView
中的值。做起来很简单。
- 创建一个符合
NSObject
的Coordinator
class
- 传递你的
LottieView
。
- 将函数
makeCoordinator
添加到您的 LottieView
- 在
makeCoordinator
函数中创建 Coordinator
的实例
- 在您的
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")
})
}
}
}
它正在运行:
这些天我一直在玩 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 的新手,所以我认为我做错了什么,因此我将不胜感激。
你快搞定了。您需要构造一个 Coordinator
以便您可以访问 LottieView
中的值。做起来很简单。
- 创建一个符合
NSObject
的 - 传递你的
LottieView
。 - 将函数
makeCoordinator
添加到您的LottieView
- 在
makeCoordinator
函数中创建Coordinator
的实例 - 在您的
updateUIView
中从coordinator
访问animationView
。
Coordinator
class
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
以下是我如何让 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")
})
}
}
}
它正在运行: