21

一度にUICollectionView1つずつ表示するために水平にスクロールするがUICollectionViewCellあります。それぞれに、セルの内容をスクロールするためのサブビューとしてUICollectionViewCell垂直スクロールがあります。セルで覆われているのは、セルUIScrollViewの内部の 90% 程度だけです。つまり、セルの外枠はこれで覆われていません。UICollectionViewCellUIScrollView

UICollectionViewCellによって覆われている の部分がデリゲートUIScrollViewをキャンセルしていることがわかります。したがって、単純なタップがセル内で発生した場合、このメソッドは呼び出されませんが、セルの外側、つまり の外側でタップが発生した場合、このメソッド呼び出されます。UICollectionViewdidSelectItemAtIndexPathUIScrollViewUIScrollView

didSelectItemAtIndexPath内でタップが発生した場合でもメソッドを呼び出すことができるセットアップを実現する方法に関する提案はありUIScrollViewますか?

4

4 に答える 4

36

最も効果的なアプローチは、panGestureRecognizerによって公開されたを盗み、 でUIScrollView無効userInteractionにすることであることがわかりましたscrollView。そうすれば、スクロールビューの動作を取得しながら、コレクション ビューでの対話を維持できます。UICollectionViewCellサブクラスで:

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

これは Apple が推奨し、WWDC 2014 セッション 235 (Advanced Scrollviews and Touch Handling Techniques) で実証している方法です。

于 2014-07-20T18:28:21.123 に答える
6

これは、セル選択機能を維持し、スクロールビューの内外で UIControl 選択 (ボタンなど) を可能にする UIScrollView サブクラス アプローチです。

スイフト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)
  }

}

スイフト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
于 2016-04-12T12:21:42.087 に答える
1

のタップは、UIScrollViewスクロールを行う必要があるかどうかを確認するために使用されます。

UIScrollView 自体の 1 回のタップをキャッチし、それを周囲の に渡す必要がありUICollectionViewCellます。

于 2013-01-12T23:00:21.273 に答える
0

スーパー ビューにタップ ジェスチャを追加する

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
        }
    }
} 
于 2018-10-21T11:20:41.483 に答える