Pass touches on some part of UICollectionView to u

2019-08-14 08:16发布

问题:

First take a look at the attacthed image:

My hiearchy looks as following:

  • UIView
    • UIButton
    • UICollectionView
      • UICollectionViewCell
      • UICollectionViewCell
      • UICollectionViewCell
      • UICollectionViewCell

UICollectionView is added to UIVew as H:[collectionView(==270)]| and V:|-(70)-[collectionView]-(70)-|.

I have two requirements:

1) only the blue part of the UICollectionViewCell should trigger the collectionView::didSelectItemAtIndexPath: method. Which I have sucesfully implemented with

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *hitView = [super hitTest:point withEvent:event];
    if (hitView == self.customView) {
        return self;
    }
    return nil;
}

on the custom class UIColectionViewCell. The customView property is the blue/red UIView of the cell. This works as expected.

2) I want any gestures (Tap/LongTap/Pan/...) that are done in the green part of the UICollectionViewCell or in the UICollectionVIew itself (the background that is here white with 0.5 opacity) to be passed down to the superview. For Example the turquoise UIButtion below. The green part should also not scroll the CollectionView .. it just has to be completly transparent to any gestures.

How can I do that? Tried a lot of different approaches but none of them worked. I know how to do it with a regular UIView, but cannot get it to work on a UICollectionView and its cells.

Keep in mind that there will be other UIViews or UIButtions that will be interactable and placed under the green part of collection view. The green color will later just be UIClearColor.

Suggestion to just have the UICollectionView smaller width (width of the blue part) is not an option since the Blue/Red part of UICell has to strecth out to full width of the cell in some cases.

回答1:

Here is the final solution for above example:

1) Require only red/blue part to be tappable. This stays basically the same. I have a reference to the blue/red UIView names customView

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *hitView = [super hitTest:point withEvent:event];
    if (hitView == self.customView) {
        return self;
    }
    return nil;
}

2) Any interactions inside the UICollectionView that are not done on blue/red UIViews should be ignored.

Subclassing UICollectionView and adding overwriting this metod:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {

    NSIndexPath *indexPath = [self indexPathForItemAtPoint:point];
    LCollectionViewCell *cell = (LCollectionViewCell*)[self cellForItemAtIndexPath:indexPath];

    if (cell && [self convertPoint:point toView:cell.customView].x >= 0) {
        return YES;
    }
    return NO;
}

This will check if the CGPoint is done on the customView. With this we are also supporting variable widths:



回答2:

Your answer helped me a ton, thanks!

Here's the solution in Swift 3.0:

 override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    let hitView = super.hitTest(point, with: event)
    if hitView == self.customView {
        return self
    }
    return nil
}