SwiftUI 动画:为什么容器视图会移动?我很难理解这种行为

Jam*_*res 3 animation ios swift swiftui

我正在构建一个简单的旋转圆加载动画。我已经让圆圈旋转,但容器视图也在动画持续时间内向下移动。我无法弄清楚是什么导致了这种奇怪的行为。

例子:

在此输入图像描述

白色边框是父视图ZStack。红色边框是VStack我放置的以显示这种奇怪的动画怪异。蓝色边框是ZStack包含两个Circle动画的 s 的 。

这是代码:

struct CustomLoadingView: View {

  let viewWidth: CGFloat = UIScreen.main.bounds.width * 0.5
  let backgroundCircleLineWidth: CGFloat = UIScreen.main.bounds.width * 0.025
  let foregroundCircleLineWidth: CGFloat = UIScreen.main.bounds.width * 0.02

  @State var rotationDegree: Angle = Angle.degrees(0)

  var body: some View {
    VStack(spacing: 0) {
        ZStack {
            Circle()
              .stroke(style: StrokeStyle(lineWidth: backgroundCircleLineWidth))
              .fill(Global.Colors.primary60)
            
            Circle()
              .trim(from: 0, to: 0.15)
              .stroke(style: StrokeStyle(lineWidth: 7, lineCap: .round))
              .fill(Global.Colors.secondary50)
              .rotationEffect(self.rotationDegree)
        }
          .frame(width: viewWidth, height: viewWidth)
          .border(Color.blue)
          .animation(Animation.linear(duration: 4.5).repeatForever(autoreverses: false), value: rotationDegree)
          .onAppear() {
              self.animateLoader()
          }
    }
      .border(Color.red)
}

   func animateLoader() {
      self.rotationDegree = .degrees(720)
   }
}
Run Code Online (Sandbox Code Playgroud)

知道为什么会发生这种情况以及如何让它停止吗?谢谢。

Jam*_*res 6

我在 vacawama 的帮助下找到了答案,他链接到了问题评论中的一个线程。该线程也有一个答案以及另一个有用的链接。这些基本上与我在这里遇到的问题相同。

这是简短而甜蜜的:

它归结为隐式动画与显式动画。在我的代码中,我使用了“显式”动画。而使用“隐式”动画 ( withAnimation()) 可以防止该问题。

显然,这可能与导航到的View动画方式有关。View就像我的情况一样,我View在导航时显示这一点。所以“导航动画”与我的显式动画混合在一起。而且,通过使用隐式动画,SwiftUI 足够智能,可以发现导航动画不应该是其中的一部分。

这是代码:

var body: some View {
    ZStack {
        Circle()
          .stroke(style: StrokeStyle(lineWidth: backgroundCircleLineWidth))
          .fill(Global.Colors.primary60)
        
        Circle()
          .trim(from: 0, to: 0.15)
          .stroke(style: StrokeStyle(lineWidth: foregroundCircleLineWidth, lineCap: .round))
          .fill(Global.Colors.secondary50)
          .rotationEffect(self.rotationDegree)
    }
      .frame(width: viewWidth, height: viewWidth)
      .onAppear() {
          DispatchQueue.main.async {
              withAnimation(Animation.linear(duration: 2.5).repeatForever(autoreverses: false)) {
                  self.rotationDegree = .degrees(720)
              }
          }
      }
}
Run Code Online (Sandbox Code Playgroud)

我只是在一个块内运行动画withAnimation()。现在它按预期工作了。