Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent touch events on subviews of scrolling UIScrollView in iOS7

I have a UIControl inside a UIScrollView. In my UIControl's init, I rig up some touch event handlers, e.g.

[self addTarget:_delegate
         action:@selector(touchedDown) forControlEvents:UIControlEventTouchDown];

iOS6 and iOS7 behave differently when I do the following:

  1. Swipe the UIScrollView to start scrolling
  2. Tap the UIScrollView to stop scrolling

In iOS6, my app continues to behave as intended: the tap at step #2 does not call touchedDown -- the UIScrollView swallows the touch event as it immediately stops scrolling.

But in iOS7, the UIScrollView stops scrolling as expected, while touchedDown is still called.

Was there a documented API change? I'd like my app to behave identically to iOS6 in iOS7.

like image 936
Emmett Avatar asked Sep 25 '13 17:09

Emmett


2 Answers

Not very elegant, but in the absence of any better ideas, here's what's working for me now:

  • On the UIScrollView, set canCancelContentTouches to YES and delaysContentTouches to NO.
  • In the UIScrollViewDelegate, toggle the UIScrollView's subview's userInteractionEnabled property when the UIScrollView scrolls:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [_contentView setUserInteractionEnabled:NO];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if (!decelerate) {
        [_contentView setUserInteractionEnabled:YES];
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [_contentView setUserInteractionEnabled:YES];
}
  • Subclass the UIScrollView and implement:
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
    return YES;
}
  • Subclass the UIControl and implement touchesCancelled:withEvent to reverse whatever the UIControlEventTouchDown handler does:
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    //custom logic
}
like image 176
Emmett Avatar answered Oct 08 '22 00:10

Emmett


workaround for iOS 7

@interface UIScrollViewFixed : UIScrollView

@end

@implementation UIScrollViewFixed

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (self.isDragging || self.isDecelerating) {
        return self;
    }
    return [super hitTest:point withEvent:event];
}

@end
like image 26
DrKLO Avatar answered Oct 08 '22 00:10

DrKLO