2
votes

I'm using scrollViewWillEndDragging:withVelocity:targetContentOffset: to snap my scrollview to pages. I customized the behavior based on the velocity. It works fine except that the scrollview decelerates too early with large offsets. The contentOffset ends up at the correct place but when the scrolling is about to end, the velocity is becoming so low that it takes about 3-4s to reach the target. The problem becomes more obvious when trying to scroll by 3-4 full screen pages. The code below is from a standalone project (Create new Single View project, add a fullscreen scrollview in the storyboard, setup iPad only, landscape mode).

FYI, changing decelerateRate doesn't solve the issue (it just makes scrolling slower/faster).

#import "ViewController.h"

@implementation ViewController
@synthesize scrollView;

- (void)viewDidLoad
{
    [super viewDidLoad];
    pages_ = 30;
    UIView* arr[pages_];
    for (int i = 0; i < pages_; ++i) {
        CGRect frame = CGRectMake(1024 * i, 0, 1024, 768);
        arr[i] = [[UIView alloc] initWithFrame:frame];
        [scrollView addSubview:arr[i]];
        arr[i].backgroundColor = (i%2) ? [UIColor redColor] : [UIColor greenColor];
    }

    scrollView.contentSize = CGSizeMake(1024 * pages_, 768);
    scrollView.delegate = self;
    scrollView.decelerationRate = UIScrollViewDecelerationRateFast;
}

- (void)scrollViewWillEndDragging:(UIScrollView *)sv
                     withVelocity:(CGPoint)velocity
              targetContentOffset:(inout CGPoint *)targetContentOffset {
    CGFloat pageWidth = scrollView.frame.size.width;
    unsigned int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;

    int scrollToPage = page + velocity.x*1.5;
    scrollToPage = MAX(0, MIN(scrollToPage, (int)pages_ - 1));
    NSLog(@"Scrolling by %d pages", abs(page-scrollToPage));

    targetContentOffset->x = scrollView.frame.size.width * scrollToPage;
    targetContentOffset->y = 0;
    NSLog(@"Scrolling to offset %f", targetContentOffset->x);
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)sv {
    NSLog(@"scrollViewDidEndDecelerating");
}

@end
1
"I'm using scrollViewWillEndDragging:withVelocity:targetContentOffset: to snap my scrollview to pages" May I ask why you're not using a paged scroll view instead? Then it would snap to pages for you. This is not a wheel you need to reinvent.matt
Because this doesn't allow you to scroll by more than one page. This method is supposed to be there so that I don't have to reinvent the wheel indeed ;-)user1727274
So why not use scroll-style UIPageViewController? Or even not scroll-style.matt

1 Answers

0
votes

After talking to some Apple engineers at WWDC, this seems to be a bug in iOS. It's probably not fixed in iOS 7