Reputation: 121
I recently study collection view. I need to let some cells fix in their own index path, which mean they should not be exchanged by others and not be dragged. I now can use *- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath )indexPath to prevent them from dragging. I cannot prevent them from being exchanged by other cells.
Any one meet same issue?
Thanks
Upvotes: 8
Views: 5554
Reputation: 3089
I found that when I used iOS 11+ drag and drop, targetIndexPathForMoveFromItemAt
wouldn't get called. Implementing this method forbids the item from being dropped where I don't want it:
func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
// disallow dragging across sections
guard let sourcePath = session.items.first?.localObject as? IndexPath,
let destPath = destinationIndexPath,
sourcePath.section == destPath.section
else {
return UICollectionViewDropProposal(operation: .forbidden)
}
return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
}
Note that I stored the source index path in localObject
when the drag started, because I couldn't find a way to get this information otherwise.
Upvotes: 5
Reputation: 2154
func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
if proposedIndexPath.row == data.count {
return IndexPath(row: proposedIndexPath.row - 1, section: proposedIndexPath.section)
} else {
return proposedIndexPath
}
}
Upvotes: 10
Reputation: 193
In this example you can't move the first and last component of your array in your CollectionView You can use porposedIndexPath, this is for UiCollectionView delegate
Swift 3
func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
if proposedIndexPath.row == 0 || proposedIndexPath.row == yourArray.count - 1{
return IndexPath(row: 1, section: 0)
}
return proposedIndexPath
}
Upvotes: 3
Reputation: 1693
Try using collectionView(_ collectionView: UICollectionView,
targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath,
toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath
See Apple's docs: https://developer.apple.com/documentation/uikit/uicollectionviewdelegate/1618052-collectionview
During the interactive moving of an item, the collection view calls this method to see if you want to provide a different index path than the proposed path. You might use this method to prevent the user from dropping the item in an invalid location. For example, you might prevent the user from dropping the item in a specific section.
So for example, if you wanted to prevent reordering a cell with the last cell you could do:
func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
if proposedIndexPath.row == data.count {
return IndexPath(row: proposedIndexPath.row - 1, section: proposedIndexPath.section)
} else {
return proposedIndexPath
}
}
Upvotes: 2