来自 @Published 属性的 SwiftUI 动画从视图外部更改
Posted
技术标签:
【中文标题】来自 @Published 属性的 SwiftUI 动画从视图外部更改【英文标题】:SwiftUI Animation from @Published property changing from outside the View 【发布时间】:2021-04-22 20:03:51 【问题描述】:SwiftUI 提供.animation()
绑定,这些绑定将为视图中的更改设置动画。但是,如果来自@ObserveredObject
的@Published
属性“自动”更改(例如,来自计时器),而视图将根据更改进行更新,则没有明显的方法可以让视图为更改设置动画。
在下面的示例中,当 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()
)
当值更改不是来自绑定时,如何触发动画?
【问题讨论】:
【参考方案1】:最简单的选择是在你的计时器闭包中添加一个withAnimation
块:
withAnimation(.easeIn(duration: 0.5))
isOn.toggle()
如果您无法更改 @ObservableObject 闭包,您可以添加一个局部变量来反映更改:
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
)
【讨论】:
以上是关于来自 @Published 属性的 SwiftUI 动画从视图外部更改的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI:“@Published”属性更改时未刷新“带有组的动态列表”
当我通过鼠标单击更改 SwiftUI 列表的选择时,@Published 属性的 didSet 被调用了两次
SwiftUI:属性装饰器的理解@State,@Binding,@ObservedObject,@Published,@Environment,@EnvironmentObject
SwiftUI:属性装饰器的理解@State,@Binding,@ObservedObject,@Published,@Environment,@EnvironmentObject