Animation SwiftUI VStack动画看起来已损坏-动画视图不会更改位置
让我们看一下以下代码片段:Animation SwiftUI VStack动画看起来已损坏-动画视图不会更改位置,animation,swiftui,vstack,Animation,Swiftui,Vstack,让我们看一下以下代码片段: struct ContentView: View { @State private var isViewHidden: Bool = false let data = [1,2,3,4,5,6,7] public var body: some View { VStack { Button("Hide", action: { withAnimation {
struct ContentView: View {
@State private var isViewHidden: Bool = false
let data = [1,2,3,4,5,6,7]
public var body: some View {
VStack {
Button("Hide", action: {
withAnimation {
isViewHidden.toggle()
}
})
ForEach(data, id: \.self) { _ in
VStack {
Text("Foo")
if isViewHidden {
Text("Bar").animation(nil)
}
}.padding().background(Color.green)
}
}
}
}
我希望文本(“隐藏”)将为父VStack中的位置设置动画。
但它将坚持到最后一个位置,然后从那里淡出,并将动画恢复到该位置。有没有可能给这个动画一个更自然的感觉,这样它将在其父动画
下面是一个gif,可以直观地显示问题:
问题在于
栏是一个新的视图
,因此只会淡出或出现在其最终目的地,因此其位置不会动画,因为它以前不在屏幕上
诀窍是始终保持条
在屏幕上,只需调整其不透明度
.offset
用于防止视图因并非始终存在的单词条而增长。添加或删除一个空白文本视图文本(“”
),以使视图像以前一样增长
以下是一个解决方案,它提供了一个外观更好的动画:
struct ContentView: View {
@State private var isViewHidden: Bool = false
let data = [1,2,3,4,5,6,7]
public var body: some View {
VStack {
Button("Hide", action: {
withAnimation {
isViewHidden.toggle()
}
})
ForEach(data, id: \.self) { _ in
VStack {
ZStack {
Text("Foo")
Text("Bar")
.offset(y: 28)
.opacity(isViewHidden ? 0 : 1)
}
if !isViewHidden {
Text(" ")
}
}.padding().background(Color.green)
}
}
}
}
在这里,它在模拟器中运行:
解决方案2:使用.matchedGeometryEffect
这里有一个解决方案,它使用.matchedGeometryEffect
在文本(“条”).frame(高度:0)
和文本(“条”)
之间设置动画
事实上我无法想象你期望什么。。。它会按要求进行动画制作。SwiftUI容器与内容紧密相连,反之亦然。。。加上“隐藏”的默认不透明度转换。。。一瞬间加上所有单元格。难道你看不到视图在动画期间是如何移出其容器的吗?要隐藏的视图的Y值越大,视图移动的次数就越多。使用.matchedGeometryEffect
,我添加了一个替代解决方案。看看吧。谢谢你在这方面做了更多的工作。我接受了这一回答,但老实说,这对我来说似乎还是有点骇人听闻。
struct ContentView: View {
@Namespace var namespace
@State private var isViewHidden: Bool = false
let data = [1,2,3,4,5,6,7]
public var body: some View {
VStack {
Button("Hide") {
withAnimation {
isViewHidden.toggle()
}
}
ForEach(data, id: \.self) { id in
VStack {
Text("Foo")
if isViewHidden {
Text("Bar").frame(height: 0)
.matchedGeometryEffect(id: id, in: namespace)
} else {
Text("Bar")
.matchedGeometryEffect(id: id, in: namespace)
}
}
.padding().background(Color.green)
}
}
}
}