UICollectionViewCell with UIScrollView cancels didSelectItemAtIndexPath

后端 未结 4 1095
野的像风
野的像风 2020-12-14 18:47

I have a UICollectionView that horizontally scrolls to show one UICollectionViewCell at a time. Each UICollectionViewCell the has a ve

相关标签:
4条回答
  • 2020-12-14 19:16

    Here's a UIScrollView subclass approach that maintains cell selection functionality, and also allows for UIControl selection (buttons, etc) both in & outside of the scrollview.

    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
    
    0 讨论(0)
  • 2020-12-14 19:22

    Add tap gesture to your super view

    override func viewDidLoad() {
            super.viewDidLoad()
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapView(gesture:)))
            view.addGestureRecognizer(tapGesture)
        }
    
    @objc func didTapView(gesture: UITapGestureRecognizer) {
        view.endEditing(true)
        let touchLocation:CGPoint = gesture.location(ofTouch: 0, in: self.collectionView)
        let indexPath = self.collectionView.indexPathForItem(at: touchLocation)
        if indexPath != nil {
            let cell = self.collectionView.cellForItem(at: indexPath!)
            if (cell?.isSelected)! {
                //PREFORM DESELECT
            } else {
                //PREFORM SELECT HERE
            }
        }
    } 
    
    0 讨论(0)
  • 2020-12-14 19:27

    I found that the most effective approach is to steal the panGestureRecognizer, exposed by UIScrollView and disable userInteraction on the scrollView. That way, you get the behavior of the scrollview but maintain the interaction on the collection view. On your UICollectionViewCell subclass:

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

    This is a method Apple recommends and demonstrates in WWDC 2014 session 235 (Advanced Scrollviews and Touch Handling Techniques)

    0 讨论(0)
  • 2020-12-14 19:41

    The tap on the UIScrollView is used to see whether scrolling should be done.

    You should catch the single tap on the UIScrollView itself and pass it on to the surrounding UICollectionViewCell.

    0 讨论(0)
提交回复
热议问题