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?
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 scroll view 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 private class extension
@property (nonatomic, assign) CGFloat lastContentOffset;
// somewhere in the class implementation
- (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 NS_ENUM(NSInteger, ScrollDirection) {
ScrollDirectionNone,
ScrollDirectionRight,
ScrollDirectionLeft,
ScrollDirectionUp,
ScrollDirectionDown,
ScrollDirectionCrazy,
};
...I would like to know which direction (left, right) the user scrolls.
In that case, on iOS 5 and above, use the UIScrollViewDelegate
to determine the direction of the user's pan gesture:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
if ([scrollView.panGestureRecognizer translationInView:scrollView.superview].x > 0) {
// handle dragging to the right
} else {
// handle dragging to the left
}
}
Using scrollViewDidScroll:
is a good way to find the current direction.
If you want to know the direction after the user has finished scrolling, use the following:
@property (nonatomic) CGFloat lastContentOffset;
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
self.lastContentOffset = scrollView.contentOffset.x;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (self.lastContentOffset > scrollView.contentOffset.x) {
// moved right if last content offset is greater then current offset
} else if (self.lastContentOffset < scrollView.contentOffset.x) {
// moved left if last content offset is less that current offset
} else {
// didn't move
}
}
No need to add an extra variable to keep track of this. Just use the UIScrollView
's panGestureRecognizer
property like this. Unfortunately, this works only if the velocity isn't 0:
CGFloat yVelocity = [scrollView.panGestureRecognizer velocityInView:scrollView].y;
if (yVelocity < 0) {
NSLog(@"Up");
} else if (yVelocity > 0) {
NSLog(@"Down");
} else {
NSLog(@"Can't determine direction as velocity is 0");
}
You can use a combination of x and y components to detect up, down, left and right.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With