【问题标题】:SwiftUI Transitions of Conditional Child Views条件子视图的 SwiftUI 转换
【发布时间】:2020-02-14 17:24:32
【问题描述】:

我正在尝试理解和试验 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 个方向起作用?

【问题讨论】:

    标签: swiftui swiftui-animation


    【解决方案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)
    }
    

    【讨论】:

    • 我明白了。所以在这种情况下,我不能对每个按钮应用单独的唯一转换?在我的示例中,一个按钮从顶部开始动画,另一个从底部开始。 (我的实际使用比发布的示例更复杂)
    【解决方案2】:

    为了得到两个不同的动画,你可以把条件逻辑拉到离按钮更近的地方,即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,但这应该不是什么大问题,至少在这个例子中是这样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-05
      • 1970-01-01
      相关资源
      最近更新 更多