3

我正在尝试理解和试验 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改变时,它在一个withAnimation块内完成。单个按钮上的转换不受支持。

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

我希望两个按钮在它们的组添加到视图时以指定的方式转换。

问题:为什么包装在 HStack 中会导致内部转换被忽略?为什么边缘过渡只在 1 个方向上起作用?

4

2 回答 2

1

为了获得两种不同的动画,您可以将条件逻辑拉近按钮,即在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)

这会给你留下一个空的HStackwhen showOverlay == false,但这应该不是什么大问题,至少在这个例子中是这样。

于 2020-02-18T11:09:38.577 回答
1

过渡适用于出现/消失的视图。在提供的代码快照中出现/消失了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)
}
于 2020-02-14T17:55:48.230 回答