SwiftUI-如何更改视图的层次结构位置?

时间:2019-06-07 01:30:08

标签: animation structure identity swiftui view-hierarchy

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

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,以便它们在垂直方向上散开并且全部可见。从ZStackVStack的变化当然算作结构的变化,因此,状态之间的所有连续性都丢失了,所有交叉的东西都消失了。有人知道该怎么做吗?

2 个答案:

答案 0 :(得分:0)

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

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

green

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

答案 1 :(得分:0)

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

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