SwiftUI中的我的动画无法正常工作

km0tfn4u  于 5个月前  发布在  Swift
关注(0)|答案(2)|浏览(79)

我在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尝试,它还是一样的。

kkih6yb8

kkih6yb81#

你定义了两种不同的状态:
1.如果showView = true,则使用RoundedRectangle
1.如果showView = false,则不使用RoundedRectangle
因此,每次showView发生变化时,body都会被重新渲染。如果它在false -> true之间切换,那么RoundedRectangle将立即显示,没有任何动画,因为它直到showView = true才出现。如果它在true -> false之间切换,那么它可以通过动画来消除,因为现在,它是视图的一部分。你可以尝试这样做,使它更平滑地显示/消失:

ZStack(alignment: .bottom) {
    VStack {
        Button("Button") {
            showView.toggle()
        }

        Spacer()
    }

    RoundedRectangle(cornerRadius: 30)
        .frame(height: showView ? (UIScreen.main.bounds.height * 0.5) : 0)
        .transition(.move(edge: .bottom))
        .animation(.easeInOut, value: showView)
}
.ignoresSafeArea(edges: .bottom)

字符串

vxqlmq5t

vxqlmq5t2#

.animation(..)放在外部包含视图中,如下所示:

ZStack(alignment: .bottom) {
    Button("Button") {
        showView.toggle()
    }
        
    if showView {
        RoundedRectangle(cornerRadius: 30)
            ...
    }
}
.ignoresSafeArea(edges: .bottom)
.animation(.easeInOut, value: showView) // <-- on ZStack, not on Rectangle

字符串
这解决了这个问题的原因是,现在SwiftUI * 总是 * 知道,showView的更改需要动画。
在您的代码中,当showView为false时,Rectangle将完全从视图层次结构中删除。这意味着:它不存在于SwiftUI中,因此它也不知道有动画。
一旦标志更改为true,SwiftUI将只进行正常的重新渲染,将看到if语句中的更改,现在将渲染Rectangle。然后 ,设置动画。 在 * 视图定义之后。所以SwiftUI将知道 * 现在 * 需要对showView的更改进行动画。但到那个时候,已经太晚了。
.animation移出if意味着,无论视图处于什么状态,动画都定义在始终存在的位置。因此,当标志更改时,SwiftUI会重新呈现并知道此更改导致的UI中的任何差异,需要进行动画处理。
Son的回答也是出于同样的原因,但使用了一种非常不同的方法。在他的回答中,SwiftUI * 总是 * 显示矩形。这意味着SwiftUI总是知道它以及在其上定义的动画。在他的回答中,他只是将视图的高度降低到0,如果它应该被隐藏的话。所以视图仍然存在,只是用户看不到它。一旦标志改变,视图不会在技术上显示,它只是动画它的高度变化。这样做可能会导致其他UI故障,这取决于你在视图中显示/隐藏的内容。在动画过程中,内容可能会被“推来推去”,挤压/拉伸等。

相关问题