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

Posted

技术标签:

【中文标题】Spring() 动画完成后 SwiftUI 执行操作【英文标题】:SwiftUI perform action after Spring() animation has completed 【发布时间】:2020-08-13 06:58:49 【问题描述】:

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

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

我可以使用计时器,但这不是一个优雅的解决方案,因为 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()
        
    


【问题讨论】:

【参考方案1】:

默认动画持续时间(对于那些没有明确的持续时间参数的动画)通常是 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 延迟,但对于人眼来说差异并不显着。

【讨论】:

谢谢!那么有没有办法做到这一点精确呢?例如。如果我想连续运行很多动画,几毫秒可以产生很大的不同...... Apple 没有为此提供明确的 API,因此任何方法或多或少都是精确的,但可以解决。随着连续的动画将是相同的。 好吧,这很不幸。希望功能尽快添加

以上是关于Spring() 动画完成后 SwiftUI 执行操作的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:在填充的水平图像中制作 y 偏移的永久动画

SwiftUI 添加自定义 UIViewControllerTransitioningDelegate

SwiftUI之深入解析如何定制视图的动画和转场

是啥导致 SwiftUI 嵌套的 View 项目在初始绘制后出现跳跃动画?

SwiftUI 五彩纸屑动画

选择后的 SwiftUI Picker 动画错误