Swiftui 条件子视图的快速转换

Swiftui 条件子视图的快速转换,swiftui,swiftui-animation,Swiftui,Swiftui Animation,我正在尝试理解并尝试使用swiftUI视图转换,并且可以深入了解为什么以下内容不能按我预期的方式工作: struct ContentView: View { @State private var showOverlay: Bool = false var body: some View { ZStack { VStack { Button(action: { withAnimation(.easeInOut) {

我正在尝试理解并尝试使用swiftUI视图转换,并且可以深入了解为什么以下内容不能按我预期的方式工作:

struct ContentView: View {
@State private var showOverlay: Bool = false

var body: some View {
    ZStack {
        VStack {
            Button(action: {
                withAnimation(.easeInOut) {
                    self.showOverlay = true
                }
            }) {
                Text("Hello, World!")
            }
        }
        .zIndex(0)
        .animation(nil)
        .blur(radius: showOverlay ? 3 : 0)

        if showOverlay {
            HStack {
                Button(action: {
                    withAnimation(.easeInOut) {
                        self.showOverlay = false
                    }
                }) {
                    Text("Close")
                }
                .frame(width: 80, height: 80)
                .background(Color.red)
                .transition(.move(edge: .top))

                Button(action: {
                    withAnimation(.easeInOut) {
                        self.showOverlay = false
                    }
                }) {
                    Text("Close")
                }
                .frame(width: 80, height: 80)
                .background(Color.red)
                .transition(.move(edge: .bottom))
            }
            .zIndex(1.0)
        }
    }
}
有两个按钮的条件HStack。 当@State参数
showOverlay
更改时,它将在
带动画的
块中完成。
单个按钮上的转换不受尊重

如果我移除HStack,并在每个按钮上放置zIndex(1),则会发生移除转换,但不会发生插入转换

我希望在将组添加到视图中时,两个按钮都以其指定的方式转换

问题: 为什么用HStack包装会导致忽略内部过渡?
为什么边缘过渡仅在一个方向上工作?

过渡适用于出现/消失的视图。在提供的代码快照中,出现/消失了
HStack
,因此应该对其应用转换

注意:转换必须在模拟器或真实设备上进行测试,大多数转换不能在预览中工作

下面是代码的修改部分,给出了工作行为。使用Xcode 11.2/iOS 13.2进行测试

if showOverlay {
    HStack {
        Button(action: {
            withAnimation(.easeInOut) {
                self.showOverlay = false
            }
        }) {
            Text("Close")
        }
        .frame(width: 80, height: 80)
        .background(Color.red)

        Button(action: {
            withAnimation(.easeInOut) {
                self.showOverlay = false
            }
        }) {
            Text("Close")
        }
        .frame(width: 80, height: 80)
        .background(Color.red)
    }
    .transition(.move(edge: .top)) // << only in this place needed
    .zIndex(1.0)
}

如果显示覆盖{
HStack{
按钮(操作:{
带动画(.easeInOut){
self.showOverlay=false
}
}) {
文本(“结束”)
}
.框架(宽度:80,高度:80)
.背景(颜色.红色)
按钮(操作:{
带动画(.easeInOut){
self.showOverlay=false
}
}) {
文本(“结束”)
}
.框架(宽度:80,高度:80)
.背景(颜色.红色)
}

.transition(.move(edge:.top))/为了获得两个不同的动画,您可以将条件逻辑拉近按钮,即在
HStack
中:

HStack {
  if showOverlay {
    Button(action: {
      withAnimation(.easeInOut) {
        self.showOverlay = false
      }
    }) {
      Text("Close")
    }
    .frame(width: 80, height: 80)
    .background(Color.red)
    .transition(.move(edge: .top))

    Button(action: {
      withAnimation(.easeInOut) {
        self.showOverlay = false
      }
    }) {
      Text("Close")
    }
    .frame(width: 80, height: 80)
    .background(Color.red)
    .transition(.move(edge: .bottom))
  }
}
.zIndex(1.0)

showOverlay==false
时,这会给您留下一个空的
HStack
,但至少在本例中,这应该不是什么问题。

我明白了。因此,在本例中,我无法对每个按钮应用单独的唯一转换?在我的示例中,一个按钮从上边缘动画,另一个按钮从下边缘动画。(我在现实世界中的使用比发布的示例更复杂)