views:

974

answers:

1

I have a UIScrollView with paging in it (so the typical model with a UIPageControl and dragging/flicking left and right between pages), and I've got that working fine. The weird thing is that when I wanted to get rid of bouncing (so that you can't see black behind the UI on the left and right sides), suddenly paging no longer works.

In other words, when:

scrollView.pagingEnabled = YES;
scrollView.bounces = YES;

Everything works fine, except I don't like the bouncing at page(0) and page(length-1). But when I do this:

scrollView.pagingEnabled = YES;
scrollView.bounces = NO;

It stops snapping into place at each page, instead treating all the pages together as one long page. So it seems that for some reason paging is dependent upon bouncing, which is fine as long as I can somehow stop the bouncing. So, is there another way to get rid of it? Or is there something I'm doing wrong?

EDIT: The solution:

@interface PagingScrollView : UIScrollView
@end

@implementation PagingScrollView

- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        self.pagingEnabled = YES;
        self.bounces = YES;
    }
    return self;
}

- (void)setContentOffset:(CGPoint)offset
{
    CGRect frame = [self frame];
    CGSize contentSize = [self contentSize];
    CGPoint contentOffset = [self contentOffset];

    // Clamp the offset.
    if (offset.x <= 0)
        offset.x = 0;
    else if (offset.x > contentSize.width - frame.size.width)
        offset.x = contentSize.width - frame.size.width;

    if (offset.y <= 0)
        offset.y = 0;
    else if (offset.y > contentSize.height - frame.size.height)
        offset.y = contentSize.height - frame.size.height;

    // Update only if necessary 
    if (offset.x != contentOffset.x || offset.y != contentOffset.y)
    {
        [super setContentOffset:offset];
    }
}

@end
+5  A: 

Your best bet would be to write an UIScrollView subclass and implement the desired behavior manually. You should be able to start with pagingEnabled and bounces both set to YES and then overwrite -setContentOffset: with your own method that clips the edges.

rpetrich
Wow, that's stupid. Well, I'll try that out, you may just be the "big winner" in this topic.
Eli
It works, but you need to override -setContentOffset, not -setContentOffset:animated, as the latter will call a function that is not always called, whereas the former overrides the mutator function for the contentOffset so you'll catch all cases.
Eli
That's odd. I do a lot of this sort of thing and usually the single parameter method calls the animated variant with animated:YES
rpetrich
This is only a problem with iOS 3.x. iOS 4.x somewhere seems to fix this. ie even with bounces set to NO, the paging still works.
Jonny