SwiftUI 在列表部分之间移动列表项

问题描述 投票:0回答:1

在下面的代码中,我试图实现从列表部分到另一个列表部分的移动(拖动)。

我有一个包含 5 个元素的枚举和一个包含这些枚举数组的状态变量 (activeElements)。 在视图中有一个包含 2 个部分的列表:

  • 第一部分包含从第 2 部分中选择的元素(我们称它们为活动元素)
  • 第二部分包含枚举中未包含在所选数组中的元素

在第 1 节中,我应该能够四处移动元素,也可以将元素拖到第 2 节的所需位置。 在第 2 节中,我应该能够将元素拖到第 1 节中,我不关心本节中的移动元素。

第 1 节完美无缺。我的问题是我无法从 section2 拖动到 section1。我只能从第 2 部分拖到第 2 部分(加号绿点只出现在那里)。 如果我将 onMove 添加到第 2 部分,我将失去从第 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)
                }
            }
        }
    }
}
list swiftui insert drag sections
1个回答
0
投票

诀窍是只使用一个 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)
}

从标题块返回任何内容以对您的项目进行分组。

© www.soinside.com 2019 - 2024. All rights reserved.