我有一个 ScrollView,其中包含顶部的固定项目和底部的未固定项目。
______________
| Item 1 |
| Item 2 |
| Item 3 |
|--------------|
| Item 4 |
| Item 5 |
| Item 6 |
| Item 7 |
| Item 8 |
|______________|
Scroll 视图由两个集合(pinnedItems 和 unpinnedItems)填充,使用 ScrollView 中的两个 ForEach 子句。
var pinnedItems = ["Item 1", "Item 2", "Item 3"]
var unpinnedItems = ["Item 4", "Item 5", "Item 6", "Item 7", "Item 8"]
ScrollView {
ForEach(pinnedTasks) { task in
NavigationLink(value: NavigationPath.task(task)) {
TaskCardView(task: task, onPinning: {
withAnimation {
togglePinnedTask(task: task)
}
})
.padding(.bottom)
}.buttonStyle(.plain)
}
Divider()
.frame(minHeight: 3)
.background(.gray)
.padding(.bottom)
ForEach(unPinnedTasks) { task in
NavigationLink(value: NavigationPath.task(task)) {
TaskCardView(task: task, onPinning: {
withAnimation {
togglePinnedTask(task: task)
}
})
.padding(.bottom)
}.buttonStyle(.plain)
}
}
togglePinnedTask() 函数从一个集合中删除任务并将其插入到另一个集合中。
自动动画只会淡化任务卡。我想让他们“飞”到新的岗位。这样做的方法是什么?
您可以使用
matchedGeometryEffect
。这是一个简单的例子:
struct ContentView: View {
@State private var pinnedItems = ["Item 1", "Item 2", "Item 3"]
@State private var unpinnedItems = ["Item 4", "Item 5", "Item 6", "Item 7", "Item 8"]
@Namespace var ns
var body: some View {
VStack {
ScrollView {
VStack {
ForEach(pinnedItems, id: \.self) { item in
Text(item)
.matchedGeometryEffect(id: item, in: ns)
}
ForEach(unpinnedItems, id: \.self) { item in
Text(item)
.matchedGeometryEffect(id: item, in: ns)
}
}
}
// as an example to trigger the animation
Button("Change Pins") {
withAnimation {
pinnedItems.append(unpinnedItems.removeLast())
}
}
}
}
}
请注意,在
matchedGeometryEffect
和 ForEach
中,我都使用 item
本身作为 id。在您的真实代码中,您的项目可能符合 Identifiable
并且您应该使用它们的 id
属性。