SwiftUI - 如何更改视图的层次位置?
Posted
技术标签:
【中文标题】SwiftUI - 如何更改视图的层次位置?【英文标题】:SwiftUI - How to change hierarchical position of View? 【发布时间】: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
当然算作结构的更改,因此状态之间的所有连续性都丢失了,一切都只是交叉淡入淡出。有谁知道该怎么办?
【问题讨论】:
【参考方案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)
【讨论】:
以上是关于SwiftUI - 如何更改视图的层次位置?的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI:如何更改 NavigationView 的色调(背景颜色)?