UIScrollView: paging horizontally, scrolling vertically?

Cited from: http://stackoverflow.com/questions/728014/prevent-diagonal-scrolling-in-uiscrollview

// RemorsefulScrollView.h

@interface RemorsefulScrollView : UIScrollView {
  CGPoint _originalPoint;
  BOOL _isHorizontalScroll, _isMultitouch;
  UIView *_currentChild;
}
@end

// RemorsefulScrollView.m

// the numbers from an example in Apple docs, may need to tune them
#define kThresholdX 12.0f
#define kThresholdY 4.0f

@implementation RemorsefulScrollView

– (id)initWithFrame:(CGRect)frame {
  if (self = [super initWithFrame:frame]) {
    self.delaysContentTouches = NO;
  }
  return self;
}

– (id)initWithCoder:(NSCoder *)coder {
  if (self = [super initWithCoder:coder]) {
    self.delaysContentTouches = NO;
  }
  return self;
}

– (UIView *)honestHitTest:(CGPoint)point withEvent:(UIEvent *)event {
  UIView *result = nil;
  for (UIView *child in self.subviews)
    if ([child pointInside:point withEvent:event])
      if ((result = [child hitTest:point withEvent:event]) != nil)
        break;
   
    if ([result isKindOfClass:[UITableView class]])
    {
        return result;
    }
   
    return nil;
}

– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event]; // always forward touchesBegan — there’s no way to forward it later
    if (_isHorizontalScroll) {
        return; // UIScrollView is in charge now
    }
    if ([touches count] == [[event touchesForView:self] count]) { // initial touch
        _originalPoint = [[touches anyObject] locationInView:self];
    _currentChild = [self honestHitTest:_originalPoint withEvent:event];
    _isMultitouch = NO;
    }
  _isMultitouch = _isMultitouch || ([[event touchesForView:self] count] > 1);
  [_currentChild touchesBegan:touches withEvent:event];
}

– (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
  if (!_isHorizontalScroll && !_isMultitouch) {
    CGPoint point = [[touches anyObject] locationInView:self];
    if (fabsf(_originalPoint.x – point.x) > kThresholdX && fabsf(_originalPoint.y – point.y) < kThresholdY) {
      _isHorizontalScroll = YES;
      [_currentChild touchesCancelled:[event touchesForView:self] withEvent:event];
    }
  }
  if (_isHorizontalScroll) {
    [super touchesMoved:touches withEvent:event]; // UIScrollView only kicks in on horizontal scroll
    }
  else {
    [_currentChild touchesMoved:touches withEvent:event];
    }
}

– (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
  if (_isHorizontalScroll) {
    [super touchesEnded:touches withEvent:event];
        _isHorizontalScroll = NO;
    }
    else {
    [super touchesEnded:touches withEvent:event];
    [_currentChild touchesEnded:touches withEvent:event];
    }
}

– (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
  [super touchesCancelled:touches withEvent:event];
  if (!_isHorizontalScroll)
    {
    [_currentChild touchesCancelled:touches withEvent:event];
        _isHorizontalScroll = NO;
    }
}

@end

Blogged with the Flock Browser
Advertisements

5 Responses to “UIScrollView: paging horizontally, scrolling vertically?”

  1. Evana Says:

    hi this is a nice post. but i want to know is there any way that i make my scrollview to do opposite behavior.like if i m dragging horizontally upwards it will scroll horizontally downwards. and the touchesmoved ir not working in SDK 3.1.

    Can you halp me about this problem…

    Thanks & Regards

    Evana

  2. What Is My IP Address Says:

    I agree with everything that was posted in this blog, I’m a loyal reader so please keep updating so frequently.

  3. Vin Decoder Says:

    if (_isHorizontalScroll) {
    [super touchesMoved:touches withEvent:event];
    }
    else {
    [_currentChild touchesMoved:touches withEvent:event];
    }

    Wouldn’t this fail on a diagonal drag?

  4. Harry Says:

    Hi, this seems to be working exapmle, but I m nt able to implement it successfully. Could u provide a xcode example project?

    Thanks

  5. 2010 in review « TEchnical SOlutions Says:

    […] UIScrollView: paging horizontally, scrolling vertically? October 2009 4 comments 3 […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: