5

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?

Rey Gonzales
  • 836
  • 1
  • 8
  • 17
  • if I understand right it's behaving like the bounces animation (also UIScrollView), so I think it is normal. The faster you go at it the faster it bounces back, if you hold in position a while the velocity with which it calculates its animation has decreased. – InvalidReferenceException Apr 03 '13 at 23:46
  • I'm actually trying to get it to behave like a UITableView or UICollectionViewFlowLayout with paging enabled. – Rey Gonzales Apr 03 '13 at 23:52
  • ok , why not then just enable paging on your scroll view? – InvalidReferenceException Apr 03 '13 at 23:54
  • I have section headers. When I enable paging, the section headers offset the view and cells are not aligned. I decided to write my own paging functionality and got most of it down until a user decided to test it and revealed to me this problem. – Rey Gonzales Apr 03 '13 at 23:57
  • maybe you could use – scrollRectToVisible:animated: every time the user has scrolled to half or more of the page to get to the next (and the opposite for going back). And leave paging enabled so if the user has not scrolled enough it will do the usual routine. – InvalidReferenceException Apr 04 '13 at 00:08
  • If anyone need any other references see this..http://stackoverflow.com/questions/14311576/pull-down-uiscrollview-and-hold-y-position/29692692#29692692 – Narasimha Nallamsetty Apr 17 '15 at 07:23
  • I have answered here check if you want... http://stackoverflow.com/questions/14311576/pull-down-uiscrollview-and-hold-y-position/29692692#29692692 – Narasimha Nallamsetty Apr 17 '15 at 07:24

1 Answers1

5

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;
}
Alessandro Orrù
  • 3,443
  • 20
  • 24
  • Hm. I imagine velocity is increased, but how can we use that to change how fast the scroll view moves to the target offset. – Rey Gonzales Apr 03 '13 at 23:48
  • @Hermione333 thought the same as me. If velocity is too high, the scrollView will move really fast to the targetPosition, so it seems like snapping back not smoothly. Look at my updated answer for a solution. – Alessandro Orrù Apr 04 '13 at 00:00
  • Thanks, I'll check this as soon as I get off the train. – Rey Gonzales Apr 04 '13 at 00:07