在 SwiftUI 中链接动画

Ron*_*zen 24 animation ios13 swiftui xcode11

我正在 SwiftUI 中处理相对复杂的动画,并且想知道链接各种动画阶段的最佳/最优雅的方式是什么。

假设我有一个视图,它首先需要缩放,然后等待几秒钟然后消失(然后等待几秒钟并重新开始 - 无限期)。

如果我尝试在同一个视图/堆栈上使用多个 withAnimation() 块,它们最终会相互干扰并弄乱动画。

到目前为止我能想到的最好的方法是在初始视图 .onAppear() 修饰符上调用一个自定义函数,在该函数中,为动画的每个阶段使用 withAnimation() 块,它们之间有延迟。所以,它基本上看起来像这样:

func doAnimations() {
  withAnimation(...)

  DispatchQueue.main.asyncAfter(...)
    withAnimation(...)

  DispatchQueue.main.asyncAfter(...)
    withAnimation(...)

  ...

}
Run Code Online (Sandbox Code Playgroud)

它最终很长而且不是很“漂亮”。我确信必须有更好/更好的方法来做到这一点,但到目前为止我尝试的一切都没有给我我想要的确切流程。

任何想法/建议/提示将不胜感激。谢谢!

mar*_*rux 23

正如其他回复中提到的,目前 SwiftUI 中没有链接动画的机制,但您不一定需要使用手动计时器。相反,您可以delay在链式动画上使用该函数:

withAnimation(Animation.easeIn(duration: 1.23)) {
    self.doSomethingFirst()
}

withAnimation(Animation.easeOut(duration: 4.56).delay(1.23)) {
    self.thenDoSomethingElse()
}

withAnimation(Animation.default.delay(1.23 + 4.56)) {
    self.andThenDoAThirdThing()
}

Run Code Online (Sandbox Code Playgroud)

我发现与使用 aDispatchQueue或 相比Timer,这会产生更一致、更流畅的链接动画,可能是因为它对所有动画使用相同的调度程序。

处理所有延迟和持续时间可能会很麻烦,因此雄心勃勃的开发人员可能会将计算抽象为某个全局withChainedAnimation函数,而不是为您处理。

  • 这对你还有效吗?它在 iOS 16 上不适用于我。在这里发布了一个带有示例的问题:/sf/ask/5179514511/使用动画查看 (2认同)

Hug*_*o F 7

使用计时器有效。这是我自己的项目:

@State private var isShowing = true
@State private var timer: Timer?

...

func askQuestion() {
    withAnimation(Animation.easeInOut(duration: 1).delay(0.5)) {
        isShowing.toggle()
    }
    timer = Timer.scheduledTimer(withTimeInterval: 1.6, repeats: false) { _ in
        withAnimation(.easeInOut(duration: 1)) {
            self.isShowing.toggle()
        }
        self.timer?.invalidate()
    }

    // code here executes before the timer is triggered.

}
Run Code Online (Sandbox Code Playgroud)


kon*_*iki 3

恐怕目前还不支持关键帧之类的东西。至少他们可以添加一个onAnimationEnd()......但没有这样的事情。

我确实有一些运气,就是对形状路径进行动画处理。尽管没有关键帧,但您拥有更多控制权,因为您可以定义“AnimatableData”。例如,请检查我对另一个问题的回答:/sf/answers/3981954651/

在这种情况下,它基本上是一个旋转的弧,但从零增长到某个长度,并在旋转结束时逐渐回到零长度。动画分为 3 个阶段:首先,弧线的一端移动,但另一端不动。然后它们以相同的速度一起移动,最后第二端到达第一端。我的第一个方法是使用 DispatchQueue 的想法,它很有效,但我同意:它非常丑陋。然后我弄清楚如何正确使用AnimatableData。所以...如果您正在制作路径动画,那么您很幸运。否则,我们似乎将不得不等待更优雅的代码的出现。