![](/img/trans.png)
[英]Nothing is happening when I call CollectionView:didSelectItemAtIndexPath
[英]collectionView didn't call didSelectItemAtIndexPath when superview has gesture
當superview有tapGesture時,collectionView沒有調用didSelectItemAtIndexPath。為什么?
為什么根據響應者鏈打印“doGesture”?
不要調用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.