Reputation: 4286
I am programmatically adding a UIButton to a custom UICollectionViewCell. Taps on the button are only detected if I do a long press on the cell first. Then the button works as expected. I have to do the same long press on each cell individually in order to get their respective button to recognize taps.
Note that single taps (i.e. didSelectItemAtIndexPath) on cells work as expected. So does long press on a cell. It might be worth noting that UILongPressGestureRecognizer is the only gesture added to the collectionView.
UICollectionViewCell class
- (UIButton *)stackInfoButton
{
if(_stackInfoButton == nil)
{
self.stackInfoButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
[self.stackInfoButton setShowsTouchWhenHighlighted:YES];
}
return _stackInfoButton;
}
- (void)layoutSubviews
{
// Other stuff here. Removed for readability
self.stackInfoFrame = CGRectMake(4.0f, self.bounds.size.height - self.stackInfoButton.bounds.size.height - 4, self.stackInfoButton.bounds.size.width, self.stackInfoButton.bounds.size.height);
}
- (void)drawRect:(CGRect)rect
{
// Other stuff here. Removed for readability
self.stackInfoButton.frame = self.stackInfoFrame;
[[self contentView] addSubview:self.stackInfoButton];
}
UICollectionViewController class
- (void)viewDidLoad
{
[super viewDidLoad];
// Other stuff here. removed for readability
self.longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
self.longPressGesture.delegate = self;
[self.collectionView addGestureRecognizer:self.longPressGesture];
self.longPressGesture.cancelsTouchesInView = NO;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
DVCardViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kDVCollectionViewCellReuseIdentifier forIndexPath:indexPath];
cell.indexPath = indexPath;
// Other stuff here. Removed for readability
[cell.stackInfoButton addTarget:self action:@selector(stackInfoButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
- (void)stackInfoButtonTapped:(id)sender
{
NSLog(@">>> Entering %s <<<", __PRETTY_FUNCTION__);
}
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
NSLog (@"Touch View : %@", touch.view);
// tried both.
// DVCardViewCell *cell;
// if (touch.view == cell.stackInfoButton)
if ( [touch.view isKindOfClass:[UIButton class]] )
{
NSLog(@"Gesture on button, returns no");
return NO;
}
NSLog(@"Gesture returns outside, yes");
return YES;
}
Suggestions appreciated. I've been through many UICollectionView threads on SO. Yet to find one that addresses my issue. Thanks.
Upvotes: 0
Views: 1098
Reputation: 650
Try this
self.LongPressGesture.cancelsTouchesInView = NO;
Sorry was mistaken. never mind.
This looks really weird:
- (UIButton *)stackInfoButton
{
if(_stackInfoButton == nil)
{
self.stackInfoButton = [UIButton buttonWithType:UIButtonTypeInfoDark]; // theoretically your app should crash now
[self.stackInfoButton setShowsTouchWhenHighlighted:YES];
}
return _stackInfoButton;
}
Look at self.stackInfoButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
It must be
_stackInfoButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
[_stackInfoButton setShowsTouchWhenHighlighted:YES];
maybe it helps.
Upvotes: 0
Reputation: 119031
You say you have added a gesture to the collection view, so you need to teach that gesture not to steal touches that it shouldn't get involved with. Add your controller as the delegate of the gesture and implement gestureRecognizer:shouldReceiveTouch:
. In that method check the view that the touch hit and, if it's a button, return NO
to prevent the gesture from getting involved.
Upvotes: 0