Reputation: 221
I have two sections in my UICollectionView. I would like to be able to drag cells within each section but not between them.
I am using a long press gesture recognizer to animate the cell drag movement so I could check that the drop location is not in a different section. Is there a way to determine a section's frame?
Or is there a simpler way?
Upvotes: 3
Views: 1999
Reputation: 31
So i ran into an issue such as the author described above, could not find a way to solve it on the Internet, eventually tried the below and it worked.
func collectionView(
_ collectionView: UICollectionView,
dropSessionDidUpdate session: UIDropSession,
withDestinationIndexPath destinationIndexPath: IndexPath?
) -> UICollectionViewDropProposal {
let sectionOfDraggableCell = 1
guard var destinationIndexPath = destinationIndexPath,
destinationIndexPath.section == sectionOfDraggableCell else {
return UICollectionViewDropProposal(operation: .forbidden)
}
return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
}
good luck.
Upvotes: 0
Reputation: 103
There is a very simple solution. I have tried it in tableView - but suppose it works fine with Collections also. Though, it's not "a clean and swifty one" - so I would suggest to use it as a temporary instrument:
Inside moveRowAt
function you check, if section in sourceIndexPath
matches a section in destinationIndexPath
. If sections are the same - you let the method to go on. If sections in are different - the function will stop.
This is how it looks like in code:
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let sourceSection = sourceIndexPath.section
let destinationSection = destinationIndexPath.section
if sourceSection == destinationSection {
// Here you can put your code, e.x:
//
//let removedItem = yourArray.remove(at: sourceIndexPath.row)
//yourArray.insert(removedItem, at: destinationIndexPath.row)
} else {
//print ("not this time")
}
}
Upvotes: 0
Reputation: 3387
In the UICollectionViewDropDelegate
, this protocol func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal
can help with it.
Check the sample below for how I prevent an item being dragged from one section to the other section:
In UICollectionViewDragDelegate, we use the itemsForBeginning
function to pass information about the object. You can see that, I passed the index and item to the localObject
func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
let item = sectionViewModel[indexPath.section].items[indexPath.row]
let itemProvider = NSItemProvider(object: item.title as NSString)
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = (item, indexPath)
return [dragItem]
}
In UICollectionViewDropDelegate, I did this:
func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
if let object = session.items.first?.localObject as? (Item, IndexPath), object.0.status, let destinationIndexPath = destinationIndexPath, object.1.section == destinationIndexPath.section {
let itemAtDestination = sectionViewModel[destinationIndexPath.section].items[destinationIndexPath.row]
if itemAtDestination.status {
return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
}
}
return UICollectionViewDropProposal(operation: .forbidden)
}
According to Apple:
While the user is dragging content, the collection view calls this method repeatedly to determine how you would handle the drop if it occurred at the specified location. The collection view provides visual feedback to the user based on your proposal. In your implementation of this method, create a UICollectionViewDropProposal object and use it to convey your intentions. Because this method is called repeatedly while the user drags over the table view, your implementation should return as quickly as possible.
What I Did: I've a couple of restrictions to cover:
Upvotes: 3