swift - 每当 SwiftUI 中的 Observed 属性发生变化时,动画 View

标签 swift swiftui

在下面的代码中,当您通过更改 @State 属性值点击图像时,该图像会产生动画效果。我希望能够做的是每次 @Published 属性值更改时为图像设置动画,该属性位于 ObservableObject 内部并且动态变化。

使用本地@State属性包装器,工作正常。

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
                }
            }
    }
}

使用观察到的@Published属性包装器,不起作用。不确定将动画放置在哪里。

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
        }
    }
}

最佳答案

我认为这里的问题是 .animation 修饰符的错误使用。

您不需要使用不同的 bool 值触发动画。如果动画是通过更改值(在本例中为 scaleValue)“驱动”的,请在修饰符中使用该值。

看看第一个示例中的动画。它没有完成。它会缩放到所需的大小,然后缩小。但它会在动画中间跳跃,同时向后收缩。

这将是您的第一个示例中的正确实现:

struct ContentView: View {
    @State private var scaleValue = 1.0
        
    var body: some View {
        
        Image(systemName: "circle.fill")
            .scaleEffect(scaleValue)
            .font(.title)
            .foregroundColor(.green)
            .animation(.easeOut(duration: 0.3), value: scaleValue)
            .onTapGesture {
                self.scaleValue = 1.5
                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3){
                    self.scaleValue = 1.0
                }
            }
    }
} 

在你的第二个例子中:

class ContentViewModel: ObservableObject{
    @Published var scaleValue = 1.0
}

struct ContentView2: View {
    @StateObject private var contentVM = ContentViewModel()
    
    var body: some View {
        
        Image(systemName: "circle.fill")
            .scaleEffect(contentVM.scaleValue)
            .font(.title)
            .foregroundColor(.green)
            .animation(.easeOut(duration: 0.3), value: contentVM.scaleValue)
            .onTapGesture {
                contentVM.scaleValue = 1.5
                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3){
                    contentVM.scaleValue = 1.0
                }
            }
    }
}

关于swift - 每当 SwiftUI 中的 Observed 属性发生变化时,动画 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75286301/

相关文章:

swiftui - 在 SwiftUI View 中使用开关/枚举

ios - 快速获取用户的联系人电话号码

swift - 在 SwiftUI 中的图像上自由手绘

binding - SwiftUI:@Binding 值更改时收到通知

ios - 从 SwiftyJSON block 访问值时遇到问题

Objective-C 可空性 : Qualifying Constant Strings

ios - Unicode箭头与文本不同

ios - 如何在 Swift 4 中使 UIDatePicker 更新文本字段和数据库

可以重新声明 Swift 内置协议(protocol)吗?为什么?

ios - 查看自定义设计