簡體   English   中英

當superview具有手勢時,collectionView沒有調用didSelectItemAtIndexPath

[英]collectionView didn't call didSelectItemAtIndexPath when superview has gesture

當superview有tapGesture時,collectionView沒有調用didSelectItemAtIndexPath。為什么?
為什么根據響應者鏈打印“doGesture”?

  1. 然后initCollectionView添加到self.view
  2. self.view中的addTapGesture
  3. 點擊iPhone中的項目。
  4. 不要調用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也可以查看。

來自Apple文檔:

當此屬性的值為false(默認值)時,視圖將分析觸摸事件的開始並與接收器並行移動。 當屬性的值為true時,窗口會暫停將UITouchPhaseBegan階段中的觸摸對象傳遞到視圖。 如果手勢識別器隨后識別其手勢,則丟棄這些觸摸對象。 但是,如果手勢識別器無法識別其手勢,則窗口會以touchesBegan( :with :)消息(以及可能的后續touchesMoved( :with :)消息將這些對象傳遞給視圖,以通知其觸摸'當前位置)。 將此屬性設置為true可防止視圖處理UITouchPhaseBegan階段中可能被識別為此手勢的一部分的任何觸摸。

編輯:為了完整性,當用戶點擊集合視圖時,我正在添加用於過濾手勢識別器處理的代碼片段。 我的方法與@ DonMag的答案中提到的方法不同。

- (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:在視圖中添加時,可能是關於手勢識別器以及它們如何工作的最清晰的解釋:

每個手勢識別器都與一個視圖相關聯。 相比之下,視圖可以具有多個手勢識別器,因為單個視圖可以響應許多不同的手勢。 要使手勢識別器識別特定視圖中發生的觸摸,您必須將手勢識別器附加到該視圖。 當用戶觸摸該視圖時,手勢識別器接收在視圖對象之前發生觸摸的消息。 結果,手勢識別器可以代表視圖響應觸摸。

設置tapGesture.cancelsTouchesInView = NO

這允許其他視圖中的觸摸通過,例如collectionView didSelectItemAtIndexPath

請注意,您將獲得tapGesture事件。 如果要在輕觸collectionViewCell時忽略它,請添加此委托方法:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
    CGPoint touchPoint = [touch locationInView:self.collectionView];
    return ![self.collectionView hitTest:touchPoint withEvent:nil];
}

如果“doGesture”出現在日志中,那么它會按預期工作,因為您在整個視圖的頂部添加了點擊識別器。 如果你想要識別水龍頭並選擇要調用,你需要自己從自來水代碼中調用didSelect。

let locationInView: CGPoint = tapGesture.location(in: self.view)
let locationInCollectionView: CGPoint = tapGesture.location(in: self.collectionView)
if let indexPath: IndexPath = collectionView.indexPathForItem(at: locationInCollectionView) {
    collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredVertically)

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM