簡體   English   中英

如何使用拖放功能重新訂購 UITableView?

[英]How can I use Drag and Drop to reorder a UITableView?

我知道拖放可用於在整個應用程序和應用程序之間傳輸數據。 我對此不感興趣。 我想要的只是使用拖放功能在不傳輸數據的情況下重新排序表視圖。 我怎么做?

如果您在本地單個項目執行拖動,則可以使用tableView(_:moveRowAt:to:) 為此,您需要實現UITableViewDragDelegate

設置

首先設置您的代表。 iPhone 需要設置dragInteractionEnabled

func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self
    tableView.delegate = self
    tableView.dragDelegate = self
    tableView.dragInteractionEnabled = true
}

UITableViewDragDelegate

請注意,該數組正在返回單個項目。 如果您返回多個項目,則將使用UITableViewDropDelegate方法而不是tableView(_:moveRowAt:to:) 您必須設置一個本地對象。

func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
    let dragItem = UIDragItem(itemProvider: NSItemProvider())
    dragItem.localObject = data[indexPath.row]
    return [ dragItem ]
}

移動

這是移動發生的地方,實際上是UITableViewDelegate的一部分。

func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    // Update the model
    let mover = data.remove(at: sourceIndexPath.row)
    data.insert(mover, at: destinationIndexPath.row)
}

如果需要,您還可以使用tableView(_:canMoveRow:at: tableView(_:targetIndexPathForMoveFromRowAt: toProposedIndexPath:)tableView(_:targetIndexPathForMoveFromRowAt: toProposedIndexPath:)

你可以在這里閱讀更多...

我發現這個問題的答案真的很令人困惑,並發現實現UITableViewDragDelegate並不是這里所需要的。 基本上:

  • 如果您只想能夠使用拖放重新排序表視圖,那么不要實現UITableViewDragDelegate而是只實現UITableViewDragDelegatefunc tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)方法:
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    // Update the model
    let mover = data.remove(at: sourceIndexPath.row)
    data.insert(mover, at: destinationIndexPath.row)
}
  • 否則,如果您希望能夠在應用程序或視圖等之間拖放項目,那么您將需要實現UITableViewDragDelegate和隨之而來的方法,例如,
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem]{
    // Handle here
}

func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
    // Handle Drop Functionality
}

等等。不會對此進行過多詳細說明,但您會在其他地方找到有關在不同視圖和應用程序之間拖放的教程。 但是,對於使用拖放對 tableview 單元格進行簡單的重新排序,請使用第一個選項並且不要實現UITableViewDragDelegate

希望這是有幫助的,因為我對這兩種方法有點困惑。

您可以在表視圖中采用拖放

為此,除了常規的delegate = selfdataSource = self ,您還需要添加

tableView.dragInteractionEnabled = true // Enable intra-app drags
tableView.dragDelegate = self
tableView.dropDelegate = self

就是這樣。 剩下的就是弄清楚如何為視覺效果和數據傳輸實現上面的委托方法。

當應用程序之間傳輸數據時,接收應用程序實現dropDelegate方法,發送應用程序實現dragDelegate方法。 現在它是同一個表視圖,它實現了兩者。

您現在可以停止閱讀,而是可以閱讀頂部的鏈接。 以下是我對鏈接文檔的理解。 我對這個話題不了解,但我自己已經成功了。

對於拖動委托

實現func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem]用於提供數據。 在許多/大多數情況下, [UIDragItem]數組僅包含 1 個元素,因為通常只拖動一項。 UIDragItem包含一個NSItemProvider對象,它攜帶傳輸的數據。

對於 dropDelegate

實現func tableView(_ tableView: UITableView, canHandle session: UIDropSession) -> Bool告訴func tableView(_ tableView: UITableView, canHandle session: UIDropSession) -> Bool是否應該處理這個放置操作。

實現func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal添加一個丟棄項目的視覺指示。 .move將添加一個“移動到那里”的動畫, .copy將添加一個加號來表示復制操作。 如果這個 func 沒有實現,你就得不到視覺提示,我不推薦它,但它仍然是可選的。

實現func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator)以實際刪除數據。 常規移動行就像將行從 A 移動到 B。A 是原始行,B 是目的地。 現在在拖放的情況下,您可以做的一種方法是,您可以從coordinator.destinationIndexPath獲取目的地 B。 A 的 indexPath 可以預先存儲在dragDelegate方法UIDragItemitemProvider ,現在通過coordinator.session.loadObject(ofClass:)將其取回。 現在您有 A 和 B,您可以執行tableView.move(at:to:)或刪除一行,然后將該行插入新的 indexPath。

同樣,您可以在頂部的鏈接中閱讀 Apple 的文檔。

在 swift 4 之后試試這個:

override func viewDidLoad() {
     super.viewDidLoad()
     self.deviceOrderingTableView.delegate = self
     self.deviceOrderingTableView.dataSource = self
     }
extension DevicesOrderingVC: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        self.model.count 
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
       //configure Cells here
    }
    func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
        true
    }
    func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        // Update the model
        self.model.swapAt(sourceIndexPath.row, destinationIndexPath.row)
        debugPrint(self.model)
        self.deviceOrderingTableView.reloadData()
    }
    func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
        return UITableViewCellEditingStyle.none
    }
    
    func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
        return false
    }

查看輸出圖像: 在此處輸入圖片說明

為此,您不需要 UITableViewDragDelegate。 當你想開始編輯/重新排列你的表時,首先添加這個: table.isEditing = true然后添加這些委托方法:

func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
    
    return true
}

func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    
    allRides.swapAt(sourceIndexPath.row, destinationIndexPath.row)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM