Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIScrollView as subview of UICollectionViewCell - passing tap to superview

I have a custom UICollectionViewCell subclass that contains a UIScrollView.

The scroll view scrolls correctly, however it intercepts taps, so that the collection view cell highlighting and selecting is not working as expected.

Setting userInteractionEnabled to NO allows taps "through" but scrolling doesn't work (of course).

Overriding hitTest:withEvent: is no use as I need to know whether it's a tap or a pan before forwarding.

Any thoughts?

like image 894
Ashley Mills Avatar asked Nov 13 '22 04:11

Ashley Mills


1 Answers

I ran into this today. Here's how I solved it, but there has to be a better way. I shouldn't have to put collection view selection logic into my cell code.

Add a UITapGestureRecognizer to the scroll view.

UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(scrollViewTapped:)];
[scrollView addGestureRecognizer:tapGesture];

Then, in the callback, you have to simulate what would happen on a normal tap on the cell:

-(void) scrollViewTapped:(UITapGestureRecognizer *)sender {
    UIView *tappedView = [sender view];

    while (![tappedView isKindOfClass:[UICollectionView class]]) {
        tappedView = [tappedView superview];
    }

    if (tappedView) {
        UICollectionView *collection = (UICollectionView *)tappedView;
        NSIndexPath *ourIndex = [collection indexPathForCell:self];
        BOOL isSelected = [[collection indexPathsForSelectedItems] containsObject:ourIndex];

        if (!isSelected) {
            BOOL shouldSelect = YES;
            if ([collection.delegate respondsToSelector:@selector(collectionView:shouldSelectItemAtIndexPath:)]) {
                shouldSelect = [collection.delegate collectionView:collection shouldSelectItemAtIndexPath:ourIndex];
            }

            if (shouldSelect) {
                [collection selectItemAtIndexPath:ourIndex animated:NO scrollPosition:UICollectionViewScrollPositionNone];
                if ([collection.delegate respondsToSelector:@selector(collectionView:didSelectItemAtIndexPath:)]) {
                    [collection.delegate collectionView:collection didSelectItemAtIndexPath:ourIndex];
                }
            }
        } else {
            BOOL shouldDeselect = YES;
            if ([collection.delegate respondsToSelector:@selector(collectionView:shouldDeselectItemAtIndexPath:)]) {
                shouldDeselect = [collection.delegate collectionView:collection shouldDeselectItemAtIndexPath:ourIndex];
            }

            if (shouldDeselect) {
                [collection deselectItemAtIndexPath:ourIndex animated:NO];
                if ([collection.delegate respondsToSelector:@selector(collectionView:didDeselectItemAtIndexPath:)]) {
                    [collection.delegate collectionView:collection didDeselectItemAtIndexPath:ourIndex];
                }
            }
        }
    }
}
like image 89
Scott K. Avatar answered Nov 15 '22 07:11

Scott K.