首页 > 解决方案 > SwiftUI 中的条件动画停止工作

问题描述

我有这个代码:

Group{
   if self.done{
      Image(systemName: "plus").font(.system(size: 40)).foregroundColor(.gray)
         .padding().overlay(Circle().stroke(Color.gray, lineWidth: 3)).opacity(0.6)
   }
   else{
      Button(action: {self.showSearchTrash = 1}){
         Image(systemName: "plus").font(.system(size: 40)).foregroundColor(green)
            .padding().overlay(Circle().stroke(green, lineWidth: 3).scaleEffect(1+self.animationAmount).animation(Animation.easeInOut(duration: 1).repeatForever(autoreverses: true)).onAppear {self.animationAmount = 0.1})
      }
   }
}.padding(.bottom, 5)

意图是如果self.donefalse,加号按钮上的圆圈将无限期地扩大和收缩。

这行得通。但是,如果我使用切换设置self.donetrue,然后将其转回false,则不再出现动画。我知道问题不在于切换开关,因为它确实恢复为绿色。

另外,缺少.beforegreen是故意的——我定义了一个特定的 Color green

知道为什么动画停止工作/如何解决这个问题吗?

标签: swiftanimationswiftui

解决方案


您可以AnimationwithAnimation块中指定并创建单独的函数来启动/停止动画。

这是一个可能的解决方案:

struct ContentView: View {
    @State private var done = false
    @State private var animationAmount: CGFloat = 0

    var body: some View {
        VStack {
            Toggle("Done", isOn: $done)
            plusImage
                .opacity(done ? 0.6 : 1)
                .foregroundColor(done ? .gray : .green)
        }
        .onAppear(perform: startAnimation)
        .onChange(of: done) { done in
            if done {
                stopAnimation()
            } else {
                startAnimation()
            }
        }
    }
    
    var plusImage: some View {
        Image(systemName: "plus")
            .font(.system(size: 40))
            .padding()
            .overlay(
                Circle()
                    .stroke(Color.gray, lineWidth: 3)
                    .scaleEffect(1 + animationAmount)
            )
    }
}
private extension ContentView {
    func startAnimation() {
        withAnimation(Animation.easeInOut(duration: 1).repeatForever()) {
            animationAmount = 0.1
        }
    }
    
    func stopAnimation() {
        withAnimation {
            animationAmount = 0
        }
    }
}

推荐阅读