I'm trying to implement drag/drop mechanics in my UICollectionView, very similar to reordering components of a shortcut in the Shortcuts app.
As of now, the behavior is that when you begin a drag, there's a transparent view of the cell left behind while another transparent view of the cell moves with the finger.
I want to get rid of the 'ghost' cell, and make the moving cell completely opaque.
Here's my drag/drop behavior (largely taken from this post)
func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
    let item = itemData[indexPath.item]
    let itemProvider = NSItemProvider(object: item.title as NSString)
    let dragItem = UIDragItem(itemProvider: itemProvider)
    dragItem.localObject = item
    return [dragItem]
}
func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
    if collectionView.hasActiveDrag {
        return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
    }
    return UICollectionViewDropProposal(operation: .forbidden)
}
func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
    var destinationIndexPath: IndexPath
    if let indexPath = coordinator.destinationIndexPath {
        destinationIndexPath = indexPath
    }
    else {
        let row = collectionView.numberOfItems(inSection: 0)
        destinationIndexPath = IndexPath(row: row - 1, section: 0)
    }
    reorderItems(coordinator: coordinator, destinationIndexPath: destinationIndexPath, collectionView: collectionView)
}
fileprivate func reorderItems(coordinator: UICollectionViewDropCoordinator,
                              destinationIndexPath: IndexPath,
                              collectionView: UICollectionView) {
    if let item = coordinator.items.first,
        let sourceIndexPath = item.sourceIndexPath {
        collectionView.performBatchUpdates({
            self.itemData.remove(at: sourceIndexPath.item)
            self.itemData.insert(item.dragItem.localObject as! PlanItem, at: destinationIndexPath.item)
            collectionView.deleteItems(at: [sourceIndexPath])
            collectionView.insertItems(at: [destinationIndexPath])
        }, completion: nil)
        coordinator.drop(item.dragItem, toItemAt: destinationIndexPath)
    }
}

not sure if question still actual, but if so: here is how you can handle cell drag state:
Is there a method to check the UICollectionView item drag cancellation if the item wasn't moved?
just do it hidden on drag, via DispatchQueue.main.async {}
and make again visible on .none state. works for me :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With