我在SwiftUI中的动画有问题,如果我使用.animation
,我的动画不工作。
ZStack(alignment: .bottom) {
VStack {
Button("Button") {
showView.toggle()
}
Spacer()
}
if showView {
RoundedRectangle(cornerRadius: 30)
.frame(height: UIScreen.main.bounds.height * 0.5)
.transition(.move(edge: .bottom))
.animation(.easeInOut, value: showView)
}
}
.ignoresSafeArea(edges: .bottom)
字符串
但如果我在按钮的action闭包中使用withAnimation
,并删除.animation
或保留它,它就可以工作。
ZStack(alignment: .bottom) {
VStack {
Button("Button") {
withAnimation {
showView.toggle()
}
}
Spacer()
}
if showView {
RoundedRectangle(cornerRadius: 30)
.frame(height: UIScreen.main.bounds.height * 0.5)
.transition(.move(edge: .bottom))
.animation(.easeInOut, value: showView)
}
}
.ignoresSafeArea(edges: .bottom)
型
有人能解释一下这是怎么工作的吗?我正在用DispatchQueue.main.async
尝试,它还是一样的。
2条答案
按热度按时间kkih6yb81#
你定义了两种不同的状态:
1.如果showView = true,则使用
RoundedRectangle
1.如果showView = false,则不使用
RoundedRectangle
因此,每次
showView
发生变化时,body
都会被重新渲染。如果它在false -> true之间切换,那么RoundedRectangle
将立即显示,没有任何动画,因为它直到showView = true
才出现。如果它在true -> false之间切换,那么它可以通过动画来消除,因为现在,它是视图的一部分。你可以尝试这样做,使它更平滑地显示/消失:字符串
vxqlmq5t2#
将
.animation(..)
放在外部包含视图中,如下所示:字符串
这解决了这个问题的原因是,现在SwiftUI * 总是 * 知道,
showView
的更改需要动画。在您的代码中,当
showView
为false时,Rectangle将完全从视图层次结构中删除。这意味着:它不存在于SwiftUI中,因此它也不知道有动画。一旦标志更改为
true
,SwiftUI将只进行正常的重新渲染,将看到if
语句中的更改,现在将渲染Rectangle。然后 ,设置动画。 在 * 视图定义之后。所以SwiftUI将知道 * 现在 * 需要对showView
的更改进行动画。但到那个时候,已经太晚了。将
.animation
移出if
意味着,无论视图处于什么状态,动画都定义在始终存在的位置。因此,当标志更改时,SwiftUI会重新呈现并知道此更改导致的UI中的任何差异,需要进行动画处理。Son的回答也是出于同样的原因,但使用了一种非常不同的方法。在他的回答中,SwiftUI * 总是 * 显示矩形。这意味着SwiftUI总是知道它以及在其上定义的动画。在他的回答中,他只是将视图的高度降低到0,如果它应该被隐藏的话。所以视图仍然存在,只是用户看不到它。一旦标志改变,视图不会在技术上显示,它只是动画它的高度变化。这样做可能会导致其他UI故障,这取决于你在视图中显示/隐藏的内容。在动画过程中,内容可能会被“推来推去”,挤压/拉伸等。