swiftui移动列表项目之间的列表部分

发布于 2025-01-27 19:54:25 字数 3801 浏览 2 评论 0原文

在“代码”中,我正在尝试实现从列表部分到另一个列表部分的移动(拖动)。

我有一个枚举,其中包含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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

请持续率性 2025-02-03 19:54:25

诀窍是只使用一个foreach。您不能在不同的“ foreach”块之间移动项目。

这对我有用:

List {    
  ForEach(0 ..< 10) { i in
    Section {
        Text(String(i))
    } header: {
        if(i==0) {
            Text("First Header")
        }
        if(i==5) {
            Text("Second Header")
        }
    }
    
  }
  .onMove(perform: move)
  .onDelete(perform: delete)
}

从头部块中返回任何内容,然后分组您的物品。

The trick is to only use ONE ForEach. You can't move items between different "ForEach" blocks.

This works for me:

List {    
  ForEach(0 ..< 10) { i in
    Section {
        Text(String(i))
    } header: {
        if(i==0) {
            Text("First Header")
        }
        if(i==5) {
            Text("Second Header")
        }
    }
    
  }
  .onMove(perform: move)
  .onDelete(perform: delete)
}

Return nothing from from header block to group your items.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文