【问题标题】:SwiftUI - How to change hierarchical position of View?SwiftUI - 如何更改视图的层次位置?
【发布时间】:2019-10-22 12:34:55
【问题描述】:

这是一个不起作用的基本示例:

import SwiftUI

struct Test : View {
    @State var swapped = false

    var body: some View {
        if swapped { Color.green }
        Color.blue.tapAction {
            withAnimation { self.swapped.toggle() }
        }
        if !swapped { Color.green }
    }
}

SwiftUI 无法弄清楚我认为第一个 Color.green 和第二个 Color.green 是同一个视图,所以当然动画只是将其中一个淡出而另一个淡入在新的地点。我正在寻找向 SwiftUI 指示这些是相同视图并将其动画化到新位置的方法。我非常兴奋地发现了.id() 修饰符,因为我相信它会给我带来我想要的效果:

import SwiftUI

struct Test : View {
    @State var swapped = false

    var body: some View {
        if swapped { Color.green.id("green") }
        Color.blue.tapAction {
            withAnimation { self.swapped.toggle() }
        }
        if !swapped { Color.green.id("green") }
    }
}

不幸的是,这也不起作用。我对 SwiftUI 感到难以置信的兴奋,但在我看来,在保持视图标识的同时更改视图层次结构的能力非常重要。促使我考虑这一点的实际用例是,我有一些视图,我正在尝试为其创建粉丝动画。最简单的方法是让ZStack 中的项目处于一种状态,以便它们都在彼此之上,然后将它们置于VStack 中处于扇出状态,以便它们垂直散开,一切可见。从ZStack 更改为VStack 当然算作结构的更改,因此状态之间的所有连续性都丢失了,一切都只是交叉淡入淡出。有谁知道该怎么办?

【问题讨论】:

    标签: animation structure identity swiftui view-hierarchy


    【解决方案1】:

    我想我已经记下了您问题的动画部分,但不幸的是,我认为它不会保留相同的视图实例。我尝试将green 放入一个变量中以查看它是否有效,但如果我正确理解 SwiftUI,这并不意味着视图的同一个实例将在两个地方共享。

    我正在做的是在添加/删除绿色视图时添加一个过渡。这样,视图会在消失之前移动到其替换位置。

    struct Test : View {
        @State var swapped = false
        let green = Color.green
    
        var body: some View {
            HStack {
                if swapped {
                    green
                        .transition(.offset(CGSize(width: 200, height: 0)))
                        .animation(.basic())
                }
                Color.blue.animation(.basic()).tapAction {
                    withAnimation { self.swapped.toggle() }
                }
                if !swapped {
                    green.transition(.offset(CGSize(width: -200, height: 0)))
                    .animation(.basic())
                }
            }
        }
    }
    

    此解决方案快速而简单,并使用基于 iPhone 6/7/8 纵向屏幕尺寸的硬编码值

    【讨论】:

    • 这不是问题的解决方案,它以非常硬编码的方式覆盖了 SwiftUI。他想要一种方法来告诉 SwiftUI 去做。
    • 这对从 ZStack 到 VStack 没有帮助。显然,他在寻求一种使用布局来定位视图并为其设置动画的方法。
    【解决方案2】:

    您可以使用 iOS 14 / macOS 10.16 中引入的 SwiftUI 2 来做到这一点:

    @Namespace private var animation
    …
    MyView.matchedGeometryEffect(id: "myID", in: animation)
    

    【讨论】:

      猜你喜欢
      • 2019-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      • 2020-01-10
      • 2020-12-23
      相关资源
      最近更新 更多