我正在尝试向我的动画添加删除动画ForEach
,使得每个Card
当移除时,其内部会扩展。这是我到目前为止所拥有的:
问题是无论哪一个Card
被按下,它是总是最后一个动画。有时,每张卡片内的文本都有奇怪的滑动/变形动画。这是我的代码:
/// Ran into this problem: "SwiftUI ForEach index out of range error when removing row"
/// `ObservableObject` solution from https://stackoverflow.com/a/62796050/14351818
class Card: ObservableObject, Identifiable {
let id = UUID()
@Published var name: String
init(name: String) {
self.name = name
}
}
struct ContentView: View {
@State var cards = [
Card(name: "Apple"),
Card(name: "Banana "),
Card(name: "Coupon"),
Card(name: "Dog"),
Card(name: "Eat")
]
var body: some View {
ScrollView(.horizontal) {
HStack {
ForEach(cards.indices, id: \.self) { index in
CardView(card: cards[index], removePressed: {
withAnimation(.easeOut) {
_ = cards.remove(at: index) /// remove the card
}
})
.transition(.scale)
}
}
}
}
}
struct CardView: View {
@ObservedObject var card: Card
var removePressed: (() -> Void)?
var body: some View {
Button(action: {
removePressed?() /// call the remove closure
}) {
VStack {
Text("Remove")
Text(card.name)
}
}
.foregroundColor(Color.white)
.font(.system(size: 24, weight: .medium))
.padding(40)
.background(Color.red)
}
}
我怎样才能横向扩展Card
单击的是,而不是最后一个?
您看到此行为的原因是因为您使用索引作为id
for ForEach
。因此,当一个元素从cards
数组,唯一的区别是ForEach
看到的是最后一个索引消失了。
您需要确保id
唯一标识每个元素ForEach
.
如果必须使用索引并标识每个元素,则可以使用enumerated
方法或zip
数组及其索引在一起。我喜欢后者:
ForEach(Array(zip(cards.indices, cards)), id: \.1) { (index, card) in
//...
}
上面使用对象本身作为ID
,这需要符合Hashable
。如果你不想这样,你可以使用id
直接属性:
ForEach(Array(zip(cards.indices, cards)), id: \.1.id) { (index, card) in
//...
}
为了完整起见,这里是enumerated
版本(从技术上讲,它不是索引,而是偏移量,但对于基于 0 的数组来说是相同的):
ForEach(Array(cards.enumerated()), id: \.1) { (index, card) in
//...
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)