我正在创建一个显示时间信息的自定义列表(分钟和秒,下面的代码段中未使用以简化代码)。当用户向列表中添加条目时,我设法实现了一个不错的动画,但是删除条目没有动画(第一个GIF)。
在iOS 14上,动画正在运行,但是,动画仅从列表中删除最后一个矩形,然后更新每行中的文本(第二个GIF)。那不是我想要的-我的目标是如果已删除一行,则其他行应填充该空间并相应地移动-并带有动画。
行ID可能有问题,但是我无法解决。感谢您的帮助!
struct ContentView: View {
@State var minutes = [0]
@State var seconds = [0]
@State var selectedElement = 0
var body: some View {
ScrollView(){
VStack{
ForEach(minutes.indices, id: \.self){ elem in
ZStack{
EntryBackground()
Text("\(self.minutes[elem])")
.transition(AnyTransition.scale)
HStack{
Button(action: {
withAnimation(.spring()){
self.seconds.remove(at: elem)
self.minutes.remove(at: elem)
}
})
{
Image(systemName: "minus.circle.fill")
.foregroundColor(Color.red)
.font(.system(size: 22))
.padding(.leading, 10)
}
Spacer()
}
}
.padding(.horizontal)
.padding(.top)
.contentShape(Rectangle())
.onTapGesture {
withAnimation(.spring()){
self.selectedElement = elem
}
}
}
}
Spacer()
Button(action: {
withAnimation{
self.minutes.append(self.minutes.count)
self.seconds.append(0)
}
})
{
ZStack{
EntryBackground()
Text("Add")
HStack{
Image(systemName: "plus.circle.fill")
.foregroundColor(Color.green)
.font(.system(size: 22))
.padding(.leading, 10)
Spacer()
}
}.padding()
}
}
}
}
struct EntryBackground: View {
var body: some View {
Rectangle()
.cornerRadius(12)
.frame(height: 40)
.foregroundColor(Color.gray.opacity(0.15))
}
}
答案 0 :(得分:5)
您需要使每一行都得到唯一标识,以便动画师知道添加了什么和删除了什么,从而正确地动画化每个更改。
这是可行的方法。经过Xcode 12 / iOS 14的测试
struct TimeItem: Identifiable, Equatable {
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.id == rhs.id
}
let id = UUID() // << identify item
let minutes: Int
let seconds: Int = 0
}
struct ContentView: View {
@State var items = [TimeItem]()
@State var selectedElement: TimeItem?
var body: some View {
ScrollView(){
VStack{
ForEach(items){ elem in // << work by item
ZStack{
EntryBackground()
Text("\(elem.minutes)")
.transition(AnyTransition.scale)
HStack{
Button(action: {
self.items.removeAll { $0.id == elem.id }
})
{
Image(systemName: "minus.circle.fill")
.foregroundColor(Color.red)
.font(.system(size: 22))
.padding(.leading, 10)
}
Spacer()
}
}
.padding(.horizontal)
.padding(.top)
.contentShape(Rectangle())
.onTapGesture {
withAnimation(.spring()){
self.selectedElement = elem
}
}
}
}
Spacer()
Button(action: {
self.items.append(TimeItem(minutes: self.items.count))
})
{
ZStack{
EntryBackground()
Text("Add")
HStack{
Image(systemName: "plus.circle.fill")
.foregroundColor(Color.green)
.font(.system(size: 22))
.padding(.leading, 10)
Spacer()
}
}.padding()
}
}.animation(.spring(), value: items) // << animate changes
}
}
struct EntryBackground: View {
var body: some View {
Rectangle()
.cornerRadius(12)
.frame(height: 40)
.foregroundColor(Color.gray.opacity(0.15))
}
}