我设法对ForEach
中显示的项目进行了很好的插入和删除动画处理(通过.transition(...)
上的Row
完成)。但是可悲的是,当我只是在观察到的数组中更新Item
的名称时,也会触发该动画。当然,这是因为它实际上是一个新视图(您可以看到,因为onAppear()
中的Row
被调用了。)
众所周知,推荐的管理带有炫酷动画的列表的方法是List
,但我认为许多人都希望避免使用标准UI或该元素附带的限制。
已附上有效的SwiftUI 示例代码段(使用Xcode 11.4构建)
所以,问题是
是否有一种聪明的方法来抑制动画(或保留另一个动画),使其保持相同的位置?是否有很酷的可能性“重用”行并进行更新?
还是答案“让我们等待下一个WWDC,让我们看看苹果是否会解决...”? ;-)
干杯,
奥兰多?
修改
当您可以区分编辑/添加/删除(例如通过手动用户操作)时,时髦的答案实际上是一个好方法。 items
数组在后台更新后(例如,通过视图模型中来自Core Data的同步更新),您不知道这是否是更新。但是,在这种情况下,答案可能是在视图模型中手动实现插入/更新/删除案例。
struct ContentView: View {
@State var items: [Item] = [
Item(name: "Tim"),
Item(name: "Steve"),
Item(name: "Bill")
]
var body: some View {
NavigationView {
ScrollView {
VStack {
ForEach(items, id: \.self) { item in
Row(name: item.name)
}
}
}
.navigationBarItems(leading: AddButton, trailing: RenameButton)
}
}
private var AddButton: some View {
Button(action: {
self.items.insert(Item(name: "Jeff"), at: 0)
}) {
Text("Add")
}
}
private var RenameButton: some View {
Button(action: {
self.items[0].name = "Craigh"
}) {
Text("Rename first")
}
}
}
struct Row: View {
@State var name: String
var body: some View {
HStack {
Text(name)
Spacer()
}
.padding()
.animation(.spring())
.transition(.move(edge: .leading))
}
}
struct Item: Identifiable, Hashable {
let id: UUID
var name: String
init(id: UUID = UUID(), name: String) {
self.id = id
self.name = name
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
答案 0 :(得分:3)
幸运的是,这实际上确实很容易做到。只需删除行上的.animation(.spring())
,然后将所有更改包装在withAnimation(.spring()) { ... }
中即可。
因此添加按钮将如下所示:
private var AddButton: some View {
Button(action: {
withAnimation(.spring()) {
self.items.insert(Item(name: "Jeff"), at: 0)
}
}) {
Text("Add")
}
}
您的行将如下所示:
struct Row: View {
@State var name: String
var body: some View {
HStack {
Text(name)
Spacer()
}
.padding()
.transition(.move(edge: .leading))
}
}