Лучшее решение на данный момент - поместить невидимый вид коллекции над значком удаления. Вот мой код:
import UIKit
class DragDropViewController: UIViewController
{
private var items1 = [String]()
//MARK: Outlets
@IBOutlet weak var collectionView1: UICollectionView!
@IBOutlet weak var collectionView2: UICollectionView!
@IBOutlet weak var trashImage: UIImageView!
private func createData(){
for index in 1...130{
items1.append("\(index)")
}
}
private func indexForIdentifier(identifier: String)->Int?{
return items1.firstIndex(of: identifier)
}
//MARK: View Lifecycle Methods
override func viewDidLoad()
{
super.viewDidLoad()
createData()
trashImage.alpha = 0
trashImage.layer.cornerRadius = 30
self.collectionView1.dragInteractionEnabled = true
self.collectionView1.dragDelegate = self
self.collectionView1.dropDelegate = self
self.collectionView2.dropDelegate = self
}
//MARK: Private Methods
/// This method moves a cell from source indexPath to destination indexPath within the same collection view. It works for only 1 item. If multiple items selected, no reordering happens.
///
/// - Parameters:
/// - coordinator: coordinator obtained from performDropWith: UICollectionViewDropDelegate method
/// - destinationIndexPath: indexpath of the collection view where the user drops the element
/// - collectionView: collectionView in which reordering needs to be done.
private func reorderItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView)
{
let items = coordinator.items
if items.count == 1, let item = items.first, let sourceIndexPath = item.sourceIndexPath
{
var dIndexPath = destinationIndexPath
if dIndexPath.row >= collectionView.numberOfItems(inSection: 0)
{
dIndexPath.row = collectionView.numberOfItems(inSection: 0) - 1
}
collectionView.performBatchUpdates({
self.items1.remove(at: sourceIndexPath.row)
self.items1.insert(item.dragItem.localObject as! String, at: dIndexPath.row)
collectionView.deleteItems(at: [sourceIndexPath])
collectionView.insertItems(at: [dIndexPath])
})
coordinator.drop(items.first!.dragItem, toItemAt: dIndexPath)
}
}
/// This method copies a cell from source indexPath in 1st collection view to destination indexPath in 2nd collection view. It works for multiple items.
///
/// - Parameters:
/// - coordinator: coordinator obtained from performDropWith: UICollectionViewDropDelegate method
/// - destinationIndexPath: indexpath of the collection view where the user drops the element
/// - collectionView: collectionView in which reordering needs to be done.
private func removeItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView)
{
collectionView.performBatchUpdates({
for item in coordinator.items
{
guard let identifier = item.dragItem.localObject as? String else {
return
}
if let index = indexForIdentifier(identifier: identifier){
let indexPath = IndexPath(row: index, section: 0)
items1.remove(at: index)
collectionView1.deleteItems(at: [indexPath])
}
}
})
}
}
// MARK: - UICollectionViewDataSource Methods
extension DragDropViewController : UICollectionViewDataSource
{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return collectionView == self.collectionView1 ? self.items1.count : 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell1", for: indexPath) as! DragDropCollectionViewCell
cell.customLabel.text = self.items1[indexPath.row].capitalized
return cell
}
}
// MARK: - UICollectionViewDragDelegate Methods
extension DragDropViewController : UICollectionViewDragDelegate
{
func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem]
{
let item = self.items1[indexPath.row]
let itemProvider = NSItemProvider(object: item as NSString)
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = item
return [dragItem]
}
func collectionView(_ collectionView: UICollectionView, itemsForAddingTo session: UIDragSession, at indexPath: IndexPath, point: CGPoint) -> [UIDragItem]
{
let item = self.items1[indexPath.row]
let itemProvider = NSItemProvider(object: item as NSString)
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = item
return [dragItem]
}
}
// MARK: - UICollectionViewDropDelegate Methods
extension DragDropViewController : UICollectionViewDropDelegate
{
func collectionView(_ collectionView: UICollectionView, canHandle session: UIDropSession) -> Bool
{
return session.canLoadObjects(ofClass: NSString.self)
}
func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal
{
if collectionView === self.collectionView1
{
return collectionView.hasActiveDrag ?
UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath) :
UICollectionViewDropProposal(operation: .forbidden)
}
else
{
if collectionView.hasActiveDrag{
return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
}
for item in session.items
{
guard let identifier = item.localObject as? String else {
return UICollectionViewDropProposal(operation: .forbidden)
}
//not every cell is allowed to be deleted
if Int(identifier)! % 3 == 0{
return UICollectionViewDropProposal(operation: .forbidden)
}
}
trashImage.backgroundColor = UIColor.red.withAlphaComponent(0.4)
return UICollectionViewDropProposal(operation: .move, intent: .unspecified)
}
}
func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator)
{
let destinationIndexPath: IndexPath
if let indexPath = coordinator.destinationIndexPath
{
destinationIndexPath = indexPath
}
else
{
// Get last index path of table view.
let section = collectionView.numberOfSections - 1
let row = collectionView.numberOfItems(inSection: section)
destinationIndexPath = IndexPath(row: row, section: section)
}
if coordinator.proposal.operation == .move{
if coordinator.proposal.intent == .insertAtDestinationIndexPath{
self.reorderItems(coordinator: coordinator, destinationIndexPath:destinationIndexPath, collectionView: collectionView)
}
else{
self.removeItems(coordinator: coordinator, destinationIndexPath: destinationIndexPath, collectionView: collectionView)
}
}
}
func collectionView(_ collectionView: UICollectionView, dropSessionDidExit session: UIDropSession) {
trashImage.backgroundColor = UIColor.clear
}
func collectionView(_ collectionView: UICollectionView, dropSessionDidEnd session: UIDropSession) {
trashImage.backgroundColor = UIColor.clear
}
}