Alex1987 Alex1987 - 6 months ago 25
iOS Question

Finding the direction of scrolling in a UIScrollView?

I have a

UIScrollView
with only horizontal scrolling allowed, and I would like to know which direction (left, right) the user scrolls. What I did was to subclass the
UIScrollView
and override the
touchesMoved
method:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];

UITouch *touch = [touches anyObject];
float now = [touch locationInView:self].x;
float before = [touch previousLocationInView:self].x;
NSLog(@"%f %f", before, now);
if (now > before){
right = NO;
NSLog(@"LEFT");
}
else{
right = YES;
NSLog(@"RIGHT");

}

}


But this method sometimes doesn't get called at all when I move. What do you think?

Answer

Determining the direction is fairly straightforward, but keep in mind that the direction can change several times over the course of a gesture. For example, if you have a scrollview with paging turned on and the user swipes to go to the next page, the initial direction could be rightward, but if you have bounce turned on, it will briefly be going in no direction at all and then briefly be going leftward.

To determine the direction, you'll need to use the UIScrollView scrollViewDidScroll delegate. In this sample, I created a variable named lastContentOffset which I use to compare the current content offset with the previous one. If it's greater, then the scrollView is scrolling right. If it's less then the scrollView is scrolling left:

//somewhere in the header
@property (nonatomic, assign) CGFloat lastContentOffset
//
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
   ScrollDirection scrollDirection;
   if (self.lastContentOffset > scrollView.contentOffset.x)
      scrollDirection = ScrollDirectionRight;
   else if (self.lastContentOffset < scrollView.contentOffset.x) 
      scrollDirection = ScrollDirectionLeft;

   self.lastContentOffset = scrollView.contentOffset.x;

   // do whatever you need to with scrollDirection here.    
}

I'm using the following enum to define direction. Setting the first value to ScrollDirectionNone has the added benefit of making that direction the default when initializing variables:

typedef enum ScrollDirection {
    ScrollDirectionNone,
    ScrollDirectionRight,
    ScrollDirectionLeft,
    ScrollDirectionUp,
    ScrollDirectionDown,
    ScrollDirectionCrazy,
} ScrollDirection;