Animation SwiftUI-如何更改视图的层次位置?
下面是一个不起作用的基本示例:Animation SwiftUI-如何更改视图的层次位置?,animation,structure,identity,swiftui,view-hierarchy,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
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当然算作结构的更改,因此状态之间的所有连续性都会丢失,所有东西都会交叉淡出。有人知道该怎么做吗?我想我已经记下了你问题中的动画部分,但不幸的是,我认为它不会保留视图的相同实例。我试着把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纵向屏幕大小的硬编码值我想我已经记下了您问题的动画部分,但不幸的是,我认为它不会保留相同的视图实例。我试着把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纵向屏幕大小的硬编码值您可以使用iOS 14/macOS 10.16中引入的SwiftUI 2来实现这一点:
@Namespace private var animation
…
MyView.matchedGeometryEffect(id: "myID", in: animation)
您可以通过iOS 14/macOS 10.16中引入的SwiftUI 2来实现这一点:
@Namespace private var animation
…
MyView.matchedGeometryEffect(id: "myID", in: animation)
这不是问题的解决方案,它以一种非常硬的编码方式覆盖SwiftUI。他想要一种方法告诉SwiftUI去做,这对从ZStack转到VStack没有帮助。很明显,他在寻求一种使用布局来定位和动画视图的方法。这不是问题的解决方案,而是以一种非常硬的编码方式覆盖SwiftUI。他想要一种方法告诉SwiftUI去做,这对从ZStack转到VStack没有帮助。很明显,他在寻求一种使用布局来定位和设置视图动画的方法。