Reputation: 6714
The default behavior while a collection view is mid-scroll:
didSelectItemAtIndexPath
What I want while a collection view is mid-scroll:
didSelectItemAtIndexPath
What would be a clean, correct approach to achieve this? FWIW, I realize this might be unexpected behavior.
Upvotes: 1
Views: 1335
Reputation: 73
In your initializer for the collection view, add an additional target for the pan gesture
self.panGestureRecognizer.addTarget(self, action: #selector(allowSelectionOfItemDuringScroll(_:)))
Then, you can implement it like this:
@objc private func allowSelectionOfItemDuringScroll(_ sender: UIPanGestureRecognizer) {
let yTranslation = sender.translation(in: self).y
var isScrolling: Bool {
if sender.state == .began {
return false
}
if isDragging && isDecelerating {
return false
}
return isDragging || isDecelerating
}
if yTranslation == 0 && isScrolling {
let selectionPoint = sender.translation(in: self)
if let index = indexPathForItem(at: selectionPoint) {
self.delegate?.collectionView?(self, didSelectItemAt: index)
}
}
Upvotes: 0
Reputation: 504
I think the best approach is to use the UICollectionView addGestureRecognizer to add a touch gesture recognizer, then process the touch gesture (e.g. get the touch location in the collection view, use that to get the indexPath of the item that was touched, then call the collectionView.didSelectItemAtIndexPath yourself). As for the scrolling, you could use the UISrollViewDelegate methods to disable user interaction on the collection view once the scroll starts, then re-enable user interaction on the collection view once the scrolling stops and/or in the viewDidDisappear view controller function.
Like this:
public class MyViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
var collectionViewTap:UITapGestureRecognizer?
override public func viewDidLoad() {
collectionViewTap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
self.view.addGestureRecognizer(collectionViewTap!)
}
override public func viewDidDisappear(animated: Bool) {
collectionView.userInteractionEnabled = true
}
func handleTap (sender:UITapGestureRecognizer) {
let touchPoint = sender.locationOfTouch(0, inView: collectionView)
let indexPath = collectionView.indexPathForItemAtPoint(touchPoint)
if (indexPath != nil) {
collectionView(collectionView, didSelectItemAtIndexPath: indexPath!)
}
}
public func scrollViewWillBeginDragging(scrollView: UIScrollView) {
collectionView.userInteractionEnabled = false
}
public func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
collectionView.userInteractionEnabled = true
}
}
Upvotes: 2