I want to revert my UIScrollView's content offset if I don't drag enough:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(CGPoint *)targetContentOffset {
self.endingOffset = scrollView.contentOffset;
if(abs(verticalOffset) > [self cellHeight] / 9) { // If the user scrolled enough distance, attempt to scroll to the next cell
...
} else if(self.nextCellOrigin.y != 0) { // The scroll view is still scrolling and the user didn't drag enough
...
} else { // If the user didn't drag enough
self.tableView.decelerationRate = UIScrollViewDecelerationRateNormal;
(*targetContentOffset) = self.startingOffset;
}
}
The code to revert to the original position is in the else portion, and it always works. However, when I don't scroll enough and make the gesture quickly, it snaps back. If I scroll just a little and then hold that position for slightly longer than usual, it reverts back smoothly.
I haven't found anything in the API reference for how long a user has touched a UIScrollView, and even if I did it's not immediately obvious how I could use that to change the behavior of my reverting code. I've also tried scrolling to the position with setContentOffset:animated: but that doesn't seem to fix the jerkiness.
Any ideas?
Have you tried logging the velocity to find out how it is when the jerkiness happens?
EDIT:
What you can try to do is implement these two scrollView delegate methods instead of the willEndDragging method. This solution will give a different feeling to the scrollView, but give it a try.
Fill the checkOffset
method with all the logic you need.
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
// if scrollView's contentOffset reached its final position during scroll, it will not decelerate, so you need a check here too
if (!decelerate) {
[self checkOffset];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
[self checkOffset];
}
- (void)checkOffset {
CGPoint newOffset;
...
// Do all the logic you need to move the content offset, then:
...
[self.scrollView setContentOffset:newOffset animated:YES];
}
EDIT #2: Maybe you could achieve a better result if you also add this to my solution.. Try ;)
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(CGPoint *)targetContentOffset {
// This should force the scrollView to stop its inertial deceleration, by forcing it to stop at the current content offset
*targetContentOffset = scrollView.contentOffset;
}