【问题标题】:SwiftUI WatchOS: Animation behaves strangely when placed inside a list?SwiftUI WatchOS:动画放在列表中时表现异常?
【发布时间】:2022-01-23 20:44:29
【问题描述】:

我在下面有这个脉冲动画,它本身运行良好,但是当我将它放在 List 内时,圆圈脉冲的动画是正确的,但所有圆圈也从顶部垂直移动到中心屏幕也是?在list 之外,圆圈仍位于中心。为什么list 会导致这种情况以及如何解决?

import SwiftUI

struct HeartRatePulseView: View {
  @State var animate = false

  @Environment(\.scenePhase) private var scenePhase

  func circlesColor() -> Color {
    Color.blue
  }

  var body: some View {
    VStack(spacing: -3) {
      ZStack {
        ZStack {
          GeometryReader { geometry in
            ZStack {
              Circle().fill(circlesColor().opacity(0.25)).frame(width: geometry.size.width, height: geometry.size.height).scaleEffect(self.animate ? 1 : 0.01)
              Circle().fill(circlesColor().opacity(0.35)).frame(width: geometry.size.width * 0.79, height: geometry.size.height * 0.79).scaleEffect(self.animate ? 1 : 0.01)
              Circle().fill(circlesColor()).frame(width: geometry.size.width * 0.60, height: geometry.size.height * 0.60)
            }
        
            .frame(width: geometry.size.width, height: geometry.size.height)
          }
        }
        .onAppear { self.animate = true }
        .onChange(of: scenePhase, perform: { newValue in
          if newValue == .active {
            self.animate = true
          } else {
            self.animate = false
          }
        })
        .animation(animate ? Animation.easeInOut(duration: 1.5).repeatForever(autoreverses: true) : .default)
    
      }
    }
    .frame(height: 145)
  }
}

struct HeartRatePulseView_Previews: PreviewProvider {
  static var previews: some View {
    List {
      HeartRatePulseView()
    }
    .listStyle(.carousel)
  }
}

【问题讨论】:

  • 详细说明最小可重复示例。
  • @Asperi 我删除了其中的一些额外元素。如果你只是将这个 view 放到 list 中(即使只是在 SwiftUI 预览中),你会看到这种行为。
  • 这似乎是 watchOS,添加一个 .border(Color.green) 显示 ZStack 完全上下移动,看起来好像坏了。如果你切换到 ScrollView 没问题,可能是 SwiftUI 错误?
  • @Chris 我应该指定是的,这是 WatchOS

标签: swift swiftui watchos swiftui-animation


【解决方案1】:

好的,如果你稍微改变一下动画方法就可以了,

注意value 参数,这似乎是动画的新方法

.animation(animate ? Animation.easeInOut(duration: 1.5).repeatForever(autoreverses: true) : nil, value: animate)
import SwiftUI

struct HeartRatePulseView: View {
  @State var animate = false

  @Environment(\.scenePhase) private var scenePhase

  func circlesColor() -> Color {
    Color.blue
  }

  var body: some View {
    VStack(spacing: -3) {
      ZStack {
        ZStack {
          GeometryReader { geometry in
            ZStack {
              Circle().fill(circlesColor().opacity(0.25)).frame(width: geometry.size.width, height: geometry.size.height).scaleEffect(self.animate ? 1 : 0.01)
              Circle().fill(circlesColor().opacity(0.35)).frame(width: geometry.size.width * 0.79, height: geometry.size.height * 0.79).scaleEffect(self.animate ? 1 : 0.01)
              Circle().fill(circlesColor()).frame(width: geometry.size.width * 0.60, height: geometry.size.height * 0.60)
            }
    
            .frame(width: geometry.size.width, height: geometry.size.height)
          }
        }
        .onAppear { self.animate = true }
        .onChange(of: scenePhase, perform: { newValue in
          if newValue == .active {
            self.animate = true
          } else {
            self.animate = false
          }
        })
        .animation(animate ? Animation.easeInOut(duration: 1.5).repeatForever(autoreverses: true) : nil, value: animate)

      }
    }
    .frame(height: 145)
  }
}

struct HeartRatePulseView_Previews: PreviewProvider {
  static var previews: some View {
    List {
      HeartRatePulseView()
      HeartRatePulseView()
    }
    .listStyle(.carousel)
  }
}

【讨论】:

  • 感谢 Chris,我构建了一个演示项目来提交错误,但也注意到我调用 animate 的方式已被贬低,因此我切换到 .animation(.easeInOut(duration: 1.5).repeatForever(autoreverses: true), value: animate),它也能正常工作?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多