swiftui移动列表项目之间的列表部分
在“代码”中,我正在尝试实现从列表部分到另一个列表部分的移动(拖动)。
我有一个枚举,其中包含5个元素和一个状态var(ActiveElements),其中包含这些枚举的数组。 在视图中,有一个带有2个部分的列表:
- 第一部分包含从第2节中选择的元素(我们称它们为活动元素)
- 中未包含的枚举元素
第二部分包含枚举 能够将元素移动,并在所需位置将元素拖到第2节。 在第2节中,我应该能够将元素拖动到第1节,我不在乎本节内的移动元素。
第1节非常完美。我的问题是我无法从第2节拖动。我只能从第2节拖动到第2节(加上绿色点仅出现在那里)。 如果我在第2节中添加onmove,我将拖动从第1节丢失到第2节。这些部分只会在其中移动元素。
您对如何实现从一个部分到另一个部分有任何建议吗?或者也许我如何在同一部分中移动2个foreach之间的元素。
这是代码:
enum RandomElements: Int, CaseIterable {
case element1 = 1
case element2 = 2
case element3 = 3
case element4 = 4
case element5 = 5
}
extension RandomElements {
var string: String {
switch self {
case .element1:
return "element1"
case .element2:
return "element2"
case .element3:
return "element3"
case .element4:
return "element4"
case .element5:
return "element5"
}
}
}
struct TwoSections: View {
@State var activeElements: [RandomElements] = []
@State var listMode: EditMode = .inactive
var body: some View {
List {
Section(header: Text("Active elements")) {
ForEach(activeElements, id: \.self) { elem in
HStack {
Text(elem.string)
Spacer()
Image(systemName: "minus")
.onTapGesture { activeElements.remove(at: activeElements.firstIndex(of: elem)!) }
}
.onDrag { NSItemProvider(object: String(elem.rawValue) as NSString ) }
}
.onInsert(of: [.plainText], perform: dropToSection1)
.onMove { (indexSet, index) in
activeElements.move(fromOffsets: indexSet, toOffset: index)
}
}
Section(header: Text("Available elements")) {
ForEach(RandomElements.allCases, id: \.self) { elem in
if !activeElements.contains(elem) {
HStack {
Text(elem.string)
Spacer()
Image(systemName: "plus")
.onTapGesture { activeElements.append(elem) }
}
.onDrag { NSItemProvider(object: String(elem.rawValue) as NSString ) }
}
}
.onInsert(of: [.plainText], perform: dropToSection2)
// .onMove { (indexSet, index) in
// }
}
}
.toolbar {
EditButton()
}
.environment(\.editMode, .constant(.active))
}
private func dropToSection1(at index: Int, _ items: [NSItemProvider]) {
for item in items {
_ = item.loadObject(ofClass: String.self) { droppedString, _ in
if let statusType = Int(droppedString ?? "") {
activeElements.remove(at: activeElements.firstIndex(of: RandomElements(rawValue: statusType)!)!)
}
}
}
}
private func dropToSection2(at index: Int, _ items: [NSItemProvider]) {
for item in items {
_ = item.loadObject(ofClass: String.self) { droppedString, _ in
if let statusType = Int(droppedString ?? "") {
print("append \(RandomElements(rawValue: statusType)!)")
activeElements.insert(RandomElements(rawValue: statusType)!, at: index)
}
}
}
}
}
In the code bellow I am trying to achieve the moving (dragging) from a list sections to another list section.
I have an enum which contains 5 elements and a state var (activeElements) that contains an array of those enum.
In a view there is a list with 2 sections:
- first section contains elements that are selected from the section 2 (let's call them active elements)
- the second section contains elements from the enum which are not contained in selected array
In section 1 I should be able to move elements around and also to drag an element to section2 at a desired position.
In section 2 I should be able to drag elements to section 1 and I don't care about the moving elements inside this section.
The section1 works perfect. My problem is that I cannot drag from section2 to section1. I can only drag from section 2 to section 2 (the plus green dot appears only there).
If I add onMove to the section 2 I lose the dragging from section 1 to section 2. The sections will move elements only inside them.
Do you have any suggestions on how to achieve moving from a section to another? Or maybe how I can move elements between 2 foreach in the same section.
Here is the code:
enum RandomElements: Int, CaseIterable {
case element1 = 1
case element2 = 2
case element3 = 3
case element4 = 4
case element5 = 5
}
extension RandomElements {
var string: String {
switch self {
case .element1:
return "element1"
case .element2:
return "element2"
case .element3:
return "element3"
case .element4:
return "element4"
case .element5:
return "element5"
}
}
}
struct TwoSections: View {
@State var activeElements: [RandomElements] = []
@State var listMode: EditMode = .inactive
var body: some View {
List {
Section(header: Text("Active elements")) {
ForEach(activeElements, id: \.self) { elem in
HStack {
Text(elem.string)
Spacer()
Image(systemName: "minus")
.onTapGesture { activeElements.remove(at: activeElements.firstIndex(of: elem)!) }
}
.onDrag { NSItemProvider(object: String(elem.rawValue) as NSString ) }
}
.onInsert(of: [.plainText], perform: dropToSection1)
.onMove { (indexSet, index) in
activeElements.move(fromOffsets: indexSet, toOffset: index)
}
}
Section(header: Text("Available elements")) {
ForEach(RandomElements.allCases, id: \.self) { elem in
if !activeElements.contains(elem) {
HStack {
Text(elem.string)
Spacer()
Image(systemName: "plus")
.onTapGesture { activeElements.append(elem) }
}
.onDrag { NSItemProvider(object: String(elem.rawValue) as NSString ) }
}
}
.onInsert(of: [.plainText], perform: dropToSection2)
// .onMove { (indexSet, index) in
// }
}
}
.toolbar {
EditButton()
}
.environment(\.editMode, .constant(.active))
}
private func dropToSection1(at index: Int, _ items: [NSItemProvider]) {
for item in items {
_ = item.loadObject(ofClass: String.self) { droppedString, _ in
if let statusType = Int(droppedString ?? "") {
activeElements.remove(at: activeElements.firstIndex(of: RandomElements(rawValue: statusType)!)!)
}
}
}
}
private func dropToSection2(at index: Int, _ items: [NSItemProvider]) {
for item in items {
_ = item.loadObject(ofClass: String.self) { droppedString, _ in
if let statusType = Int(droppedString ?? "") {
print("append \(RandomElements(rawValue: statusType)!)")
activeElements.insert(RandomElements(rawValue: statusType)!, at: index)
}
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
诀窍是只使用一个foreach。您不能在不同的“ foreach”块之间移动项目。
这对我有用:
从头部块中返回任何内容,然后分组您的物品。
The trick is to only use ONE ForEach. You can't move items between different "ForEach" blocks.
This works for me:
Return nothing from from header block to group your items.