I have a UICollectionView where only some of the cells are selectable. I want tapping on any other cells, as well as anywhere else on the screen, to invoke the navigation bar hiding/revealing behavior.
When I set navigationController.hidesBarsOnTap = true, the barHideOnTapGestureRecognizer consumes the taps so the user can't select an item in the collection view. How can I have both the bar hiding behavior and normal collection view selection behavior?
If I set barHideOnTapGestureRecognizer.cancelsTouchesInView = false, then both the item is selected and the bar hiding toggles, but I want only the former.
I can't do anything in the barHideOnTapGestureRecognizer delegate as Apple explicitly says not to.
UICollectionView doesn't use a gesture recognizer to do its selection, so there's no way to set up dependencies between that and the barHideOnTapGestureRecognizer.
The only thing that comes to mind is to manage the collection selection manually with a tap gesture recognizer covering the whole collection (Apple says not to put them on individual cells), but it seems crazy to duplicate all the collection view selection. I've gotta be missing something. Please, help me see the light! :)
In the end, I added a UITapGestureRecognizer to the UICollectionView, and set the recognizer's delegate to return true from shouldReceiveTouch only if the touch was within a cell I wanted to be selectable.
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
for visibleCell in collectionView.visibleCells() {
if let selectableCell = visibleCell as? SelectableCell
where touch.view!.isDescendantOfView(selectableCell) {
return true
}
}
return false
}
Thus, the recognizer will fire only for touches in cells I want to be selectable, leaving all other touches within the collection view to be picked up by the barHideOnTapGestureRecognizer.
In the tap gesture recognizer's triggered action, I use hit testing on the visibleCells to locate the selected cell, and invoke the selection.
I had to set navigationController.barHideOnTapGestureRecognizer.cancelsTouchesInView = true to prefer the gesture recognizer on the collection view for touches.
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