I'm trying to implement a custom tab bar which is scrollable and has paging at each tab bar item. For that i'm using the delegate scrollViewWillEndDragging:withVelocity:targetContentOffset: which works perfectly with one problem.
The way my paging works is, if the contentOffset is near the right item, it the targetContentOffset changes to the offset of that item. Same thing for the left side.
The problem is, whenever I'm at at the left half of the first item and the right of the last (the scroll view works horizontally) it's supposed to go to ContentOffset 0 and the content offset of the rightmost item (minus the ones on screen), but it doesn't.
I checked with the debugger and the targetContentOffset->x is indeed 0 (in the first case - left of the leftmost item). So the problem is the UIScrollView not scrolling there. I'm lost.
Here is my implemented delegate:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset{
NSInteger index = lrintf(targetContentOffset->x/self.tabWidth);
targetContentOffset->x = index * self.tabWidth;
}
Here is the diagram explaining what i want to do.
|-------|-------|-------|-------|-------|-------|-------|
| | | | | | | |
| | | | | | | |
|_______|_______|_______|_______|_______|_______|_______|
|_______________________________________|
where it is and i scroll it to the left
<----|
|_______________________________________|
where it would stop
|_______________________________________|
where i want it to stop
I tried setting the final offset to something slightly off zero or the content size as suggested by Big Papoo but noticed that this removes the over-scroll bounce. My solution to this was to check the original targetContentOffset to see if it is equal to zero or the contentSize and leaving it if it is:
You can of course then use
scrollViewDidEndDecelerating:
to to move the scrollview that 1 point.This is a known issue it seems. After some investigation and talking to other people it was suggested it could be a bug, which turned out to be correct. I reported it to Apple and was it marked as duplicate but is still open. Just answering for those of you with the same problem. I workaround it like Big Papoo suggests, by using an offset close to what I want (0.1 seems to do it). The same for the right end.
Issue Fixed on iOS 6.0.
Now it works as it should.
If you're using a horizontal table view, then inside your scrollViewWillEndDragging:withVelocity:targetContentOffset: function, you can call:
I found this to work much better than trying to manipulate targetContentOffset->y in a horizontal table view.
I found 2 undocumented behaviors that you may investigate : - Setting zero as the final offset doesn't work, I suggest putting 1 or anything greater than zero (0.5 may work, not tested) - You'd better check the velocity sign and compute your final offset to be on the left or right side of the current point where the user removed is finger. Don't try to make the scrolling go backward on the other side.