gpt4 book ai didi

animation - 来自 @Published 属性的 SwiftUI 动画从 View 外部更改

转载 作者:行者123 更新时间:2023-12-05 02:00:34 26 4
gpt4 key购买 nike

SwiftUI 在绑定(bind)上提供了 .animation() 可以使 View 中的变化具有动画效果。但是,如果 @ObserveredObject 中的 @Published 属性“自动”更改(例如,来自计时器),而 View 将响应更改而更新,则没有获取 View 以动画更改的明显方法。

在下面的示例中,当 isOn 从 Toggle 更改时,它会设置动画,但当从 Timer 更改时,它不会。有趣的是,如果我在这里使用三元条件而不是 if/else,即使切换也不会触发动画。

struct ContentView: View {
@ObservedObject var model: Model
var body: some View {
VStack {
if model.isOn {
MyImage(color: .blue)
} else {
MyImage(color: .clear)
}
Spacer()
Toggle("switch", isOn: $model.isOn.animation(.easeIn(duration: 0.5)))
Spacer()
}
}
}

struct MyImage: View {
var color: Color
var body: some View {
Image(systemName: "pencil.circle.fill")
.resizable()
.frame(width: 100, height: 100)
.foregroundColor(color)
}
}

class Model: ObservableObject {
@Published var isOn: Bool = false
var timer = Timer()
init() {
timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true, block: { [unowned self] _ in
isOn.toggle()
})
}
}

当值更改不是来自绑定(bind)时,如何触发动画?

最佳答案

最简单的选择是在您的计时器闭包中添加一个 withAnimation block :

withAnimation(.easeIn(duration: 0.5)) {
isOn.toggle()
}

如果您无法更改@ObservableObject 闭包,您可以添加一个局部变量来反射(reflect)更改:

struct ContentView: View {
@ObservedObject var model: Model
@State var localIsOn = false
var body: some View {
VStack {
if localIsOn {
MyImage(color: .blue)
} else {
MyImage(color: .clear)
}
Spacer()
Toggle("switch", isOn: $model.isOn.animation(.easeIn(duration: 0.5)))
Spacer()
}.onChange(of: model.isOn) { (on) in
withAnimation {
localIsOn = on
}
}
}
}

你也可以在你的 ObservableObject 中使用一个镜像变量来做一个类似的技巧:


struct ContentView: View {
@ObservedObject var model: Model
var body: some View {
VStack {
if model.animatedOn {
MyImage(color: .blue)
} else {
MyImage(color: .clear)
}
Spacer()
Toggle("switch", isOn: $model.isOn.animation(.easeIn(duration: 0.5)))
Spacer()
}
}
}


class Model: ObservableObject {
@Published var isOn: Bool = false
@Published var animatedOn : Bool = false

var cancellable : AnyCancellable?

var timer = Timer()
init() {
timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true, block: { [unowned self] _ in
isOn.toggle()
})
cancellable = $isOn.sink(receiveValue: { (on) in
withAnimation {
self.animatedOn = on
}
})
}
}

关于animation - 来自 @Published 属性的 SwiftUI 动画从 View 外部更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67220033/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com