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 {
                    isViewHidden.toggle()
                }
            })
            ForEach(data,id: \.self) { _ in
                vstack {
                    Text("Foo")
                    if isViewHidden {
                        Text("Bar").animation(nil)
                    }
                }.padding().background(Color.green)
            }
        }
    }
}

我希望Text(“ Hide”)将使父vstack内部的位置动起来。 但是它会坚持到最后一个位置,然后从那里消失,并重新设置动画。是否有可能使该动画更自然,从而使其在其父级内部进行动画处理。

以下是显示问题的gif文件

enter image description here

解决方法

问题在于Bar是新的View,因此会淡出或出现在其最终目的地,因此它的位置不会动起来,因为它先前不在屏幕上。

诀窍是始终将Bar保持在屏幕上,而只需调整其opacity。由于.offset并不总是出现,因此Bar用于防止视图增长。添加或删除空白文本视图Text(" "),以使视图像以前一样增长。

以下是可以使动画效果更好的解决方法:

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)
            }
        }
    }
}

它在模拟器中运行:

Demo in the siumlator


解决方案2:使用.matchedGeometryEffect

这是一个使用.matchedGeometryEffectText("Bar").frame(height: 0)Text("Bar")之间进行动画处理的解决方案。

struct ContentView: View {
    @Namespace var namespace
    @State private var isViewHidden: Bool = false
    let data = [1,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)
            }
        }
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...