Spring() 动画完成后 SwiftUI 执行操作

leo*_*oe1 13 animation ios swift swiftui

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

我做了一些研究,发现了另一种方法:SwiftUI withAnimation 完成回调。然而,在此解决方案中,动画对象的偏移量与原点进行比较,因此与上述问题相同。

我可以使用计时器,但这不是一个优雅的解决方案,因为 Spring() 动画的持续时间会根据其开始位置动态变化,所以这不是方法。

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

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

在此输入图像描述

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

Run Code Online (Sandbox Code Playgroud)

Asp*_*eri 14

默认动画持续时间(对于那些没有显式持续时间参数的动画)通常为 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
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:您可以调整 0.5 的延迟,但对于人眼来说差异并不显着。

  • 好吧,那是非常不幸的。希望尽快添加功能 (3认同)