当超级视图有手势时,collectionView 没有调用 didSelectItemAtIndexPath [英] collectionView didn't call didSelectItemAtIndexPath when superview has gesture

查看:29
本文介绍了当超级视图有手势时,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 阶段中可能被识别为的任何触摸这个手势的一部分.

When the value of this property is false (the default), views analyze touch events in began and moved in parallel with the receiver. When the value of the property is true, the window suspends delivery of touch objects in the UITouchPhaseBegan phase to the view. If the gesture recognizer subsequently recognizes its gesture, these touch objects are discarded. If the gesture recognizer, however, does not recognize its gesture, the window delivers these objects to the view in a touchesBegan(:with:) message (and possibly a follow-up touchesMoved(:with:) message to inform it of the touches’ current locations). Set this property to true to prevent views from processing any touches in the UITouchPhaseBegan phase that may be recognized as part of this gesture.

为了完整起见,当用户点击集合视图时,我添加了用于过滤手势识别器处理的代码片段.我的方法与@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:

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

Every gesture recognizer is associated with one view. By contrast, a view can have multiple gesture recognizers, because a single view might respond to many different gestures. For a gesture recognizer to recognize touches that occur in a particular view, you must attach the gesture recognizer to that view. When a user touches that view, the gesture recognizer receives a message that a touch occurred before the view object does. As a result, the gesture recognizer can respond to touches on behalf of the view.

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

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆