【发布时间】:2022-01-19 07:21:38
【问题描述】:
我在SwiftUI 中有一个奇怪的动画行为。我试图创建一个最小的视图来演示它。
我想用淡入淡出和缩放效果在三个圆圈中制作动画(请参阅下面的“我的期望”栏)。但是,圆圈的大小取决于视图的宽度,所以我使用GeometryReader 来获得它。
我想在.onAppear(perform:) 中开始动画,但是在调用的时候,GeometryReader 还没有设置size 属性。我最终得到的是您在 “Unwanted Animation 1” 中看到的动画。这是因为帧从 .zero 动画到正确的大小。
但是,每当我尝试通过添加.animation(nil, value: size) 修饰符来禁用帧的动画时,我都会得到一个非常奇怪的动画行为(参见“Unwanted Animation 2”)。这个我完全不明白。它以某种方式为动画添加了水平平移,使其看起来更糟。任何想法这里发生了什么以及如何解决这个问题?
奇怪的是,如果我使用这样的显式动画,一切都会正常工作:
.onAppear {
withAnimation {
show.toggle()
}
}
但我想了解这里发生了什么。
谢谢!
更新:
用以下代码替换.onAppear(perform:) 是否合理?这只会在视图的生命周期内触发一次,就在 size 从 .zero 更改为正确值时。
.onChange(of: size) { [size] newValue in
guard size == .zero else { return }
show.toggle()
}
import SwiftUI
struct TestView: View {
@State private var show = false
@State private var size: CGSize = .zero
var body: some View {
VStack {
circle
circle
circle
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.contentShape(Rectangle())
.background {
GeometryReader { proxy in
Color.clear.onAppear { size = proxy.size }
}
}
.onAppear { show.toggle() }
}
private var circle: some View {
Circle()
.frame(width: circleSize, height: circleSize)
.animation(nil, value: size) // This make the circles animate in from the side for some reason (see "Strange Animation 2")
.opacity(show ? 1 : 0)
.scaleEffect(show ? 1 : 2)
.animation(.easeInOut(duration: 1), value: show)
}
private var circleSize: Double {
size.width * 0.2 // Everything works fine if this is a constant
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
【问题讨论】:
标签: ios swift animation swiftui