向 ForEach 循环元素添加动画 (SwiftUI)
Add animations to ForEach loop elements (SwiftUI)
有什么方法可以在 ForEach 循环的元素出现或消失时添加动画?
我尝试过以多种方式使用 withAnimation{} 和 .animation(),但它们似乎不起作用
这是一些代码 (Xcode 11 beta 5):
import SwiftUI
struct test: View {
@State var ContentArray = ["A","B","C"]
var body: some View {
ScrollView{
VStack{
ForEach(ContentArray.indices, id: \.self){index in
ZStack{
// Object
Text(self.ContentArray[index])
.frame(width:100,height:100)
.background(Color.gray)
.cornerRadius(20)
.padding()
//Delete button
Button(action: {
self.ContentArray.remove(at: index)
}){
Text("✕")
.foregroundColor(.white)
.frame(width:40,height:40)
.background(Color.red)
.cornerRadius(100)
}.offset(x:40,y:-40)
}
}
}
}
}
}
#if DEBUG
struct test_Previews: PreviewProvider {
static var previews: some View {
test()
}
}
#endif
如下图所示,没有动画,一切都显得非常突兀。非常感谢任何解决方案
重要提示:当元素数量发生变化时,布局应该像List一样改变。例如,当一个top对象被删除时,每个对象都会自动移到top
看来这个问题还是最新的(Xcode11.4),因为直接复制粘贴观察到的效果是一样的。所以,这里有几个问题:首先,它需要正确设置动画和过渡的组合;其次,ForEach
容器必须知道删除的确切项目,因此必须标识项目,而不是匿名的索引。
结果我们得到如下效果(transition/animation也可以是其他的):
struct TestAnimationInStack: View {
@State var ContentArray = ["A","B","C", "D", "E", "F", "G", "I", "J"]
var body: some View {
ScrollView{
VStack{
ForEach(Array(ContentArray.enumerated()), id: \.element){ (i, item) in // << 1) !
ZStack{
// Object
Text(item)
.frame(width:100,height:100)
.background(Color.gray)
.cornerRadius(20)
.padding()
//Delete button
Button(action: {
withAnimation { () -> () in // << 2) !!
self.ContentArray.remove(at: i)
}
}){
Text("✕")
.foregroundColor(.white)
.frame(width:40,height:40)
.background(Color.red)
.cornerRadius(100)
}.offset(x:40,y:-40)
}.transition(AnyTransition.scale) // << 3) !!!
}
}
}
}
}
有什么方法可以在 ForEach 循环的元素出现或消失时添加动画?
我尝试过以多种方式使用 withAnimation{} 和 .animation(),但它们似乎不起作用
这是一些代码 (Xcode 11 beta 5):
import SwiftUI
struct test: View {
@State var ContentArray = ["A","B","C"]
var body: some View {
ScrollView{
VStack{
ForEach(ContentArray.indices, id: \.self){index in
ZStack{
// Object
Text(self.ContentArray[index])
.frame(width:100,height:100)
.background(Color.gray)
.cornerRadius(20)
.padding()
//Delete button
Button(action: {
self.ContentArray.remove(at: index)
}){
Text("✕")
.foregroundColor(.white)
.frame(width:40,height:40)
.background(Color.red)
.cornerRadius(100)
}.offset(x:40,y:-40)
}
}
}
}
}
}
#if DEBUG
struct test_Previews: PreviewProvider {
static var previews: some View {
test()
}
}
#endif
如下图所示,没有动画,一切都显得非常突兀。非常感谢任何解决方案
重要提示:当元素数量发生变化时,布局应该像List一样改变。例如,当一个top对象被删除时,每个对象都会自动移到top
看来这个问题还是最新的(Xcode11.4),因为直接复制粘贴观察到的效果是一样的。所以,这里有几个问题:首先,它需要正确设置动画和过渡的组合;其次,ForEach
容器必须知道删除的确切项目,因此必须标识项目,而不是匿名的索引。
结果我们得到如下效果(transition/animation也可以是其他的):
struct TestAnimationInStack: View {
@State var ContentArray = ["A","B","C", "D", "E", "F", "G", "I", "J"]
var body: some View {
ScrollView{
VStack{
ForEach(Array(ContentArray.enumerated()), id: \.element){ (i, item) in // << 1) !
ZStack{
// Object
Text(item)
.frame(width:100,height:100)
.background(Color.gray)
.cornerRadius(20)
.padding()
//Delete button
Button(action: {
withAnimation { () -> () in // << 2) !!
self.ContentArray.remove(at: i)
}
}){
Text("✕")
.foregroundColor(.white)
.frame(width:40,height:40)
.background(Color.red)
.cornerRadius(100)
}.offset(x:40,y:-40)
}.transition(AnyTransition.scale) // << 3) !!!
}
}
}
}
}