SwiftUI在Spring动画完成后执行操作

问题描述

我试图弄清楚如何在SwiftUI中检测动画是否完成,具体来说就是:Spring()动画。我的第一个想法是使用GeometryReader来检测以下示例中的圆形何时到达原点(偏移= .zero),但是这种方法一个警告:Spring()动画超出了该点它应该在哪里结束然后反弹。因此,“动画结束”将在动画完成之前触发。

我做了一些研究,发现了另一种方法SwiftUI withAnimation completion callback。但是,在此解决方案中,将动画对象的偏移量与原点进行了比较,因此存在与上述相同的问题。

我可以使用计时器,但这并不是一个很好的解决方案,因为Spring()动画的持续时间根据它的开始位置而动态变化,所以不是这样。

在下面的示例中,我希望动画结束后圆圈变为绿色。

有没有办法解决这个问题?感谢您的帮助!

enter image description here

struct ContentView: View {
    
    @State var offset: CGSize = .zero
    @State var animationRunning = false
    
    var body: some View {
        
        vstack {
            Circle()
                .foregroundColor(self.animationRunning ? .red : .green)
                .frame(width: 200,height: 200)
                .offset(self.offset)
                .gesture(
                    DragGesture()
                        .onChanged{ gesture in
                            self.offset = gesture.translation
                    }
                    .onEnded{_ in
                        self.animationRunning = true
                        
                        withAnimation(.spring()){
                            self.offset = .zero
                        }
                })
            Spacer()
        }
    }
}

解决方法

默认动画持续时间(对于没有显式持续时间参数的动画)通常为0.25-0.35(与启动位置和平台无关),因此在您的情况下,它是完全安全的(使用Xcode 11.4 / iOS 13.4测试) )使用以下方法:

withAnimation(.spring()){
    self.offset = .zero
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        self.animationRunning = false
    }
}

注意:您可以调整0.5个延迟,但对人眼而言,差异并不明显。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...