当超级视图有手势时

当超级视图有手势时

本文介绍了当超级视图有手势时,collectionView 没有调用 didSelectItemAtIndexPath的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当superview有tapGesture时collectionView没有调用didSelectItemAtIndexPath.这是为什么?
为什么它根据响应者链打印doGesture"?

collectionView didn't call didSelectItemAtIndexPath when superview has tapGesture。is why?
why it print "doGesture" according to the Responder Chain?

  1. initCollectionView 然后添加到 self.view
  2. 在 self.view 中添加TapGesture
  3. 点击 iPhone 中的项目.
  4. 不调用 didSelectItemAtIndexPath.

  1. initCollectionView then add to self.view
  2. addTapGesture in self.view
  3. click item in iPhone.
  4. not call didSelectItemAtIndexPath.

- (void)viewDidLoad {
    [super viewDidLoad];
    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
    self.collectionView = [[MyCollectionView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 100) collectionViewLayout:flowLayout];
    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"abc"];
    self.collectionView.delegate = self;
    self.collectionView.dataSource = self;
    [self.view addSubview:self.collectionView];

    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doGesture)];
    tapGesture.delegate = self;
    [self.view addGestureRecognizer:tapGesture];
}

- (void)doGesture
{
    NSLog(@"%@",@"doGesture");
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 100;
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"%@",@"didSelectItemAtIndexPath");
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"abc" forIndexPath:indexPath];
    if (indexPath.row %2==0) {
        cell.backgroundColor = [UIColor redColor];
    } else{
        cell.backgroundColor = [UIColor grayColor];
    }
    return cell;
}

推荐答案

你需要设置tapGesture.cancelsTouchesInView = NO.

根据您的逻辑,您可能还想查看 delaysTouchesBegan.

Depending on Your logic You may want to check out delaysTouchesBegan too.

来自 Apple 文档:

From Apple docs:

当该属性的值为false(默认)时,views分析触摸事件开始并与接收器并行移动.什么时候属性值为真,窗口暂停传递将 UITouchPhaseBegan 阶段中的对象触摸到视图.如果手势识别器随后识别出它的手势,这些触摸对象被丢弃.但是,如果手势识别器没有识别它的手势,窗口将这些对象传递给视图在 touchesBegan(:with:) 消息中(可能还有后续touchesMoved(:with:) 消息通知它触摸的当前位置).将此属性设置为 true 以防止处理视图UITouchPhaseBegan 阶段中可能被识别为的任何触摸这个手势的一部分.

为了完整起见,当用户点击集合视图时,我添加了用于过滤手势识别器处理的代码片段.我的方法与@DonMag 的回答中提到的方法不同.

EDIT :For completeness I am adding code snippet for filtering the gesture recognizer's handling, when the user taps in on the collection view. My approach is different from the one mentioned in @DonMag's answer.

- (void)doGesture:(UIGestureRecognizer*) sender
{
    CGPoint locationInView = [sender locationOfTouch:0 inView:self.view];
    CGPojnt convertedLocation = [self.collectionView convertPoint:location fromView:self.view];

    // from Apple doc
    // Returns a Boolean value indicating whether the receiver contains the specified point.
    if (![self.collectionView pointInside:convertedLocation withEvent:nil])
    {
      NSLog(@"%@",@"doGesture");
    }
}

编辑 2:当添加到视图中时,这可能是对手势识别器及其工作方式最清晰的解释:

EDIT 2:Maybe the clearest explanation about gesture recognizers and how they work, when added in views:

每个手势识别器都与一个视图相关联.相比之下,一个视图可以有多个手势识别器,因为单个视图可能会响应许多不同的手势.对于手势识别器识别发生在特定视图中的触摸,您必须附加该视图的手势识别器.当用户触摸该视图时,手势识别器收到一条消息,在此之前发生了触摸视图对象确实如此.因此,手势识别器可以响应代表视图接触.

这篇关于当超级视图有手势时,collectionView 没有调用 didSelectItemAtIndexPath的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 19:07