将项目从一个列表拖动到 SwiftUI 中的另一个列表 [英] Drag item from one List to another List in SwiftUI

查看:31
本文介绍了将项目从一个列表拖动到 SwiftUI 中的另一个列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个列表,每个列表都有简单的项目.我可以重新排列列表中的项目,代码如下所示.我希望能够从一个列表中拖动一个项目并将其放入另一个列表中.不确定我需要启用什么才能实现这一点.照原样,我可以从一个列表中将某些内容拖到整个屏幕上,但是除了它自己的列表之外,我不能将它放在任何地方;如果我在其他任何地方释放阻力,它就会飞回原来的位置.

I have two Lists each with simple items. I can rearrange items within a list, with the code shown below. I want to be able to drag an item from one list and drop it into the other list. Not sure what I need to enable to make that happen. As is, I can drag something from one list all over the screen, but I can't drop it anywhere except within its own list; if I release the drag anywhere else, it just flies back to its original location.

显然,我需要添加一些东西来启用所需的行为;任何关于所需内容的想法(不一定使用 .onMove - 在同一个列表中)将不胜感激.

Clearly, I need to add something(s) to enable the desired behavior; any ideas on what's required (not necessarily using .onMove -- that's within the same list) would be most appreciated.

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)
    }
}

推荐答案

我认为这在 SwiftUI 中是不可能的.这段代码展示了如何使用两个 UITableViews.我希望您能对此进行改进以实现您的目标.

I don't think this is possible with SwiftUI yet. This piece of code shows how you use two UITableViews. I hope you can improve this to achieve what you are looking for.

首先创建这个具有所有魔力的类.您需要导入UIKitMobileCoreServices.

First create this class which does all the magic. You need to import UIKit and 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()
        }
    }
}

我希望这会有所帮助.

这篇关于将项目从一个列表拖动到 SwiftUI 中的另一个列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆