0

I have a bit of a complex situation involving multiple gestures. Basically, I want to have one container UIScrollView that only scrolls left-to-right if the touches are within a specific area. If they are not within the area, the UIScrollView passes those touches on to child UIViews that exist side-by-side inside the UIScrollView (think of it like a panel navigation).

I have the UIScrollView containing UIViews working fine. I subclassed UIScrollView and added the panning restriction via TouchesBegan/TouchesMoved/TouchesEnded/TouchesCancelled. Everything works except when the UIView is a UITableView. It seems at that point my parent UIScrollView never gets these events and so can never restrict the panning properly.

Anyone have any ideas for how to accomplish this?

Thanks!

  • Take a look at how `-hittest:withEvent` is modified .[How to ignore touch events and pass them to another subview's UIControl objects?](http://stackoverflow.com/questions/7719412/how-to-ignore-touch-events-and-pass-them-to-another-subviews-uicontrol-objects) – lead_the_zeppelin May 05 '14 at 15:33
  • This led me down a path that ended up working really well! – Miron Vranješ May 06 '14 at 07:40

1 Answers1

1

The way to do this is to subclass the subviews that are eating the touch events and not allowing the UIScrollView to get them. Then, override the pointInside: method (with the appropriate exception for UI that you want to still work). For example:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
// Confine the offending control to a certain area
CGRect frame = CGRectMake(0, 0,
                          self.frame.size.width,
                          self.frame.size.height - 100.00);

// Except for subview buttons (or some other UI element)
if([self depthFirstButtonTest:self pointInside:point withEvent:event])
{
    return YES;
}

return (CGRectContainsPoint(frame, point));
}

- (BOOL)depthFirstButtonTest:(UIView*)view pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
for (UIView * subview in view.subviews)
{
    if([self depthFirstButtonTest:subview pointInside:point withEvent:event])
    {
        return YES;
    }
}

// Is it a button? If so, perform normal testing on it
if ([view isKindOfClass:[UIButton class]]) {
    CGPoint pointInButton = [view convertPoint:point fromView:self];
    if ([view pointInside:pointInButton withEvent:event]) {
        return YES;
    }
}

return NO;
}