Перетащите элемент из одного списка в другой список в SwiftUI - PullRequest
2 голосов
/ 21 октября 2019

У меня есть два списка, каждый с простыми предметами. Я могу переставить элементы в списке, используя код, показанный ниже. Я хочу иметь возможность перетаскивать элемент из одного списка и помещать его в другой список. Не уверен, что мне нужно, чтобы это произошло. Таким образом, я могу перетащить что-то из одного списка по всему экрану, но я не могу удалить это нигде, кроме как в пределах своего собственного списка;если я отпущу перетаскивание в другом месте, он просто вернется в исходное положение.

Очевидно, что мне нужно добавить что-то (ы), чтобы включить желаемое поведение;Любые идеи о том, что требуется (не обязательно с использованием .onMove - это в том же списке), будут наиболее ценными.

struct ContentView: View {
    @State private var users1 = ["AAA", "BBB", "CCC"]
    @State private var users2 = ["DDD", "EEE", "FFF"]
    @State private var isEditable = true

    var body: some View {
        HStack {
            Spacer()
            List {
                ForEach(users1, id: \.self) { user in
                    Text(user)
                        .background(Color(.yellow))
                }
                .onMove(perform: move1)
            }
            .environment(\.editMode, isEditable ? .constant(.active) : .constant(.inactive))
            Spacer()
            List {
                ForEach(users2, id: \.self) { user in
                    Text(user)
                        .background(Color(.orange))
                }
                .onMove(perform: move2)
            }
            .environment(\.editMode, isEditable ? .constant(.active) : .constant(.inactive))
            Spacer()
        }
    }
    func move1(from source: IndexSet, to destination: Int) {
        users1.move(fromOffsets: source, toOffset: destination)
    }
    func move2(from source: IndexSet, to destination: Int) {
        users2.move(fromOffsets: source, toOffset: destination)
    }
}

1 Ответ

1 голос
/ 30 октября 2019

Я не думаю, что это возможно с SwiftUI пока. Этот фрагмент кода показывает, как вы используете два UITableViews. Я надеюсь, что вы можете улучшить это, чтобы достичь того, что вы ищете.

Сначала создайте этот класс, который делает всю магию. Вам нужно импортировать UIKit и MobileCoreServices.

class TableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITableViewDragDelegate, UITableViewDropDelegate {

    var leftTableView = UITableView()
    var rightTableView = UITableView()

    var removeIndex = IndexPath()

    var leftItems: [String] = [
        "Hello",
        "What",
        "is",
        "happening"
    ]
    var rightItems: [String] = [
        "I",
        "don't",
        "know"
    ]

    func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
        let string = tableView == leftTableView ? leftItems[indexPath.row] : rightItems[indexPath.row]
        self.removeIndex = indexPath
        guard let data = string.data(using: .utf8) else { return [] }
        let itemProvider = NSItemProvider(item: data as NSData, typeIdentifier: kUTTypePlainText as String)

        return [UIDragItem(itemProvider: itemProvider)]
    }

    func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
        let destinationIndexPath: IndexPath

        if let indexPath = coordinator.destinationIndexPath {
            destinationIndexPath = indexPath
        } else {
            let section = tableView.numberOfSections - 1
            let row = tableView.numberOfRows(inSection: section)
            destinationIndexPath = IndexPath(row: row, section: section)
        }

        coordinator.session.loadObjects(ofClass: NSString.self) { items in
            guard let strings = items as? [String] else {
                return
            }
            var indexPaths = [IndexPath]()
            for (index, string) in strings.enumerated() {
                let indexPath = IndexPath(row: destinationIndexPath.row + index, section: destinationIndexPath.section)
                if tableView == self.leftTableView {
                    self.leftItems.insert(string, at: indexPath.row)
                } else {
                    self.rightItems.insert(string, at: indexPath.row)
                }
                indexPaths.append(indexPath)
            }
            if tableView == self.leftTableView {
                self.rightItems.remove(at: self.removeIndex.row)
                self.rightTableView.deleteRows(at: [self.removeIndex], with: .automatic)
            } else {
                self.leftItems.remove(at: self.removeIndex.row)
                self.leftTableView.deleteRows(at: [self.removeIndex], with: .automatic)
            }
            tableView.insertRows(at: indexPaths, with: .automatic)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        leftTableView.dataSource = self
        rightTableView.dataSource = self

        leftTableView.frame = CGRect(x: 0, y: 40, width: 150, height: 400)
        rightTableView.frame = CGRect(x: 150, y: 40, width: 150, height: 400)

        leftTableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
        rightTableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")

        view.addSubview(leftTableView)
        view.addSubview(rightTableView)

        leftTableView.dragDelegate = self
        leftTableView.dropDelegate = self
        rightTableView.dragDelegate = self
        rightTableView.dropDelegate = self

        leftTableView.dragInteractionEnabled = true
        rightTableView.dragInteractionEnabled = true
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if tableView == leftTableView {
            return leftItems.count
        } else {
            return rightItems.count
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        if tableView == leftTableView {
            cell.textLabel?.text = leftItems[indexPath.row]
        } else {
            cell.textLabel?.text = rightItems[indexPath.row]
        }

        return cell
    }
}

. После этого вы оборачиваете это:

struct TableView: UIViewControllerRepresentable {

    func makeUIViewController(context: Context) -> TableViewController {
        let v = TableViewController()
        return v
    }

    func updateUIViewController(_ viewController: TableViewController, context: Context) {

    }

}

и, наконец, используете его:

struct ContentView: View {


    var body: some View {
        VStack {
            TableView()
        }
    }
}

Надеюсь, это поможет.

...