Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIScrollView inside a UITableViewCell - No didSelect call

I have a tableviewCell, where the user can scroll horizontally. Since the scrollView covers nearly the whole cell, the tableView method didSelectRow gets not called if the user clicks the cell.

So I thought, I could pass the touch event of the UIScrollView to the cell, but still the didSelectRow doesnt gets called. I subclassed UIScrollView to pass the touch event only, if the touch was not a drag:

- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event
{
    NSLog(@"touch scroll");
    // If not dragging, send event to next responder
    if (!self.dragging)
        [self.superview touchesEnded: touches withEvent:event];
    else
        [super touchesEnded: touches withEvent: event];
}

Any ideas on how to pass the click to the table, to get the delegate-methods called and keep the scrolling inside the scrollview?

like image 443
Grinarn Avatar asked Feb 25 '13 09:02

Grinarn


3 Answers

You can actually do this without subclassing UIScrollView. Whether you have a custom cell, or are setting properties in cellForRowAtIndexPath in the UITableView, you can do the following:

[cell.contentView addSubview:yourScrollView];
yourScrollView.userInteractionEnabled = NO;
[cell.contentView addGestureRecognizer:yourScrollView.panGestureRecognizer];

The reason you can do this is because scrollView has its own panGestureRecognizer that's accessible to the programmer. So, just adding it to the cell's view will trigger the scrollview's gesture delegates.

The only drawback of this approach is that subviews of the scroll view are unable to receive any touch input. If you need this you will have to chose a different approach.

like image 53
cph2117 Avatar answered Nov 15 '22 07:11

cph2117


I just encountered the same problem.
In your subclass make sure to include the full set of methods:

-(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!self.dragging)
        [self.superview touchesCancelled: touches withEvent:event];
    else
        [super touchesCancelled: touches withEvent: event];
}

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!self.dragging)
        [self.superview touchesMoved: touches withEvent:event];
    else
        [super touchesMoved: touches withEvent: event];
}

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!self.dragging)
        [self.superview touchesBegan: touches withEvent:event];
    else
        [super touchesBegan: touches withEvent: event];
}

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!self.dragging)
        [self.superview touchesEnded: touches withEvent:event];
    else
        [super touchesEnded: touches withEvent: event];
}
like image 28
gils Avatar answered Nov 15 '22 08:11

gils


The selected answer is correct, but I updated the code based on a bug I was getting.

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if (self.dragging) {
        [super touchesMoved:touches withEvent:event];
    } else {
        if ([self.delegate isKindOfClass:[UITableViewCell class]]) {
            [(UITableViewCell *)self.delegate touchesCancelled:touches withEvent:event];
        }

        [self.superview touchesMoved:touches withEvent:event];
    }
}

If your self.delegate is not the UITableViewCell, than replace that property with a property to your cell.

The cell needs to retrieve the cancel touch event during movement to prevent the undesired results. It can be easily reproducible as follows.

  • Highlight the cell (assuming the scroll view is over the whole cell, if not highlight the scroll view)
  • While the cell is highlighted, drag the table view
  • Select any other cell and now the previously highlighted cell will retrieve the didSelectCell state

Another point to mention is that order matters! If the self.delegate is not called before the self.superview then the highlighted state wont happen.

like image 22
cnotethegr8 Avatar answered Nov 15 '22 09:11

cnotethegr8