在下面的代码中,当你点击一个Image的时候,通过改变@State
属性值,它会被动画化。我想做的是,每当@Published
属性值改变的时候,动画化这个图像,这个属性位于ObservableObject
中,并且是动态改变的。
使用Local @State属性 Package 器可以正常工作。
struct ContentView: View {
@State private var scaleValue = 1.0
@State private var isAnimating: Bool = true
var body: some View {
Image(systemName: "circle.fill")
.scaleEffect(scaleValue)
.font(.title)
.foregroundColor(.green)
.animation(.easeOut(duration: 0.3), value: isAnimating)
.onTapGesture {
self.isAnimating.toggle()
self.scaleValue = 1.5
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3){
self.scaleValue = 1.0
}
}
}
}
正在使用Observed @Published属性 Package ,但不起作用。不确定将动画放在何处。
struct ContentView: View {
@State private var scaleValue = 1.0
@StateObject private var contentVM = ContentViewModel()
var body: some View {
Image(systemName: "circle.fill")
.scaleEffect(scaleValue)
.font(.title)
.foregroundColor(.green)
.animation(.easeOut(duration: 0.3), value: contentVM.isAnimating)
// not sure where to add the animation
}
}
编辑:以下是工作溶液:
感谢@Fogmeister和@burnsi
class ContentViewModel: ObservableObject{
@Published var isAnimatingImage = false
}
struct ContentView2: View {
@StateObject private var contentVM = ContentViewModel()
var body: some View {
@State private var scaleValue = 1.0
Image(systemName: "circle.fill")
.scaleEffect(scaleValue)
.font(.title)
.foregroundColor(.green)
.animation(.easeOut(duration: 0.3), value: scaleValue)
.onChange(of: contentVM.isAnimatingImage) {newValue in
animateImage()
}
}
func animateImage(){
scaleValue = 1.5
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3){
scaleValue = 1.0
}
}
}
2条答案
按热度按时间r1zk6ea11#
我认为这里的问题是
.animation
修饰符的错误用法。你不需要用不同的布尔值来触发动画。如果动画是通过改变一个值来“驱动”的,在这个例子中是
scaleValue
,在修改器中使用那个值。看看你的第一个例子中的动画。它没有完成。它缩放到所需的大小,然后收缩。但是它在收缩回来的同时跳到了动画的中间。
这将是第一个示例中的正确实现:
在第二个例子中
xdnvmnnf2#
这就是为什么我们不应该在SwiftUI中使用视图模型对象,这也不是
@StateObject
的设计目的-它是为我们需要@State
中的引用类型而设计的,而这里不是这样。如果你想将视图数据变量分组在一起,你可以将它们放在一个结构中,例如: