Подтвердить что ты не робот

UICollectionViewCell с отменой UIScrollView didSelectItemAtIndexPath

У меня есть UICollectionView, который горизонтально прокручивает, чтобы показывать один UICollectionViewCell за раз. Каждый UICollectionViewCell имеет вертикальную прокрутку UIScrollView как подпункт для прокрутки содержимого ячейки. Это всего лишь 90% внутренней части UICollectionViewCell, которая покрывается UIScrollView, то есть внешний кадр ячейки не покрывается этим.

Оказывается, что часть UICollectionViewCell, которая покрывается UIScrollView, отменяет делегат UICollectionView didSelectItemAtIndexPath. Таким образом, когда простое нажатие происходит в UIScrollView, этот метод не вызывается, тогда как если крана происходит во внешней части ячейки, то есть вне UIScrollView, этот метод вызывается.

Любые предложения относительно того, как достичь настройки, где можно вызвать метод didSelectItemAtIndexPath, даже если кратковременное нажатие происходит в UIScrollView?

4b9b3361

Ответ 2

Я обнаружил, что наиболее эффективным подходом является кража panGestureRecognizer, открытая UIScrollView и отключая userInteraction в scrollView. Таким образом, вы получаете поведение scrollview, но поддерживаете взаимодействие в представлении коллекции. В подклассе UICollectionViewCell:

self.scrollView.userInteractionEnabled = NO;
[self.contentView addGestureRecognizer:self.scrollView.panGestureRecognizer];

Это метод, который Apple рекомендует и демонстрирует в сессии WWDC 2014 235 (Advanced Scrollviews и Touch Handling Techniques)

Ответ 3

Здесь применяется подкласс UIScrollView, который поддерживает функциональность выбора ячеек, а также позволяет выбирать UIControl (кнопки и т.д.) как внутри, так и вне прокрутки.

Swift 3

class CellContentScrollView: UIScrollView {

  override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    let hitTargetView = super.hitTest(point, with: event)
    return hitTargetView as? UIControl ?? (hitTargetView == self ? nil : superview)
  }

  override func didMoveToSuperview() {
    superview?.addGestureRecognizer(panGestureRecognizer)
  }

}

Swift 2

class CellContentScrollView: UIScrollView {

    // MARK: - UIView override

    override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
        let hitTargetView = super.hitTest(point, withEvent: event)
        return hitTargetView as? UIControl ?? (hitTargetView == self ? nil : superview)
    }

    override func didMoveToSuperview() {
        superview?.addGestureRecognizer(panGestureRecognizer)
    }
}

Objective-C

@implementation CellContentScrollView

    #pragma mark - UIView override

    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
        UIView *hitTargetView = [super hitTest:point withEvent:event];

        if ([hitTargetView isKindOfClass:UIControl.class]) {
            return hitTargetView;
        } else if (hitTargetView != self) {
            return self.superview;
        }

        return nil;
    }

    - (void)didMoveToSuperview {
        [self.superview addGestureRecognizer:self.panGestureRecognizer];
    }

@end