Iphone – Photos app-like gap between pages in UIScrollView with pagingEnabled

cocoa-touchiphoneuiscrollview

UIScrollView in paging mode assumes the pages are located right next to each other, with no gap. However if you open a photo in the Photos app and swipe through photos, you can see that it has some gap between pages. I want these gaps too.

I'm looking for existing solutions if any, or for some more bizarre ideas about implementing the page gaps besides the one I have explained below. Or maybe there's some obvious easy way I am missing?

To be clear: I want the gap to only be visible while scrolling, so I cannot simply inset the page content.


My plan is to try moving the page content from inside scrollViewDidScroll callback, so that (assuming you're scrolling to the right) initially the target page is slightly offset to the right of its page boundaries, and by the time you arrive at the target page it's back at its proper location, and the source page is slightly offset to the left of its boundaries. (Or maybe instead of moving things continuously, I'll be better off shifting the offsets, say, exactly halfway between pages.)

I'm the author of the ScrollingMadness article+example that I've been referring some people to here. I've implemented progammatic zooming, and got in-photo zooming+scrolling working together with inter-photo paging. So I know how to play with UIScrollView, and am looking for the advanced stuff.

Please don't point me at TTScrollView. I've already pointed many people to it myself, but I consider it's feel too far from the native UIScrollView behaviour, and do not want to use it in my projects.

Best Answer

Note that this answer is quite old. The basic concept still works but you should not be hard coding view sizes in iOS7 and 8. Even if you ignore that advice, you should not use 480 or 330.

Have you tried making the frame of the UIScrollView slightly larger than the screen (assuming that you want to display your images fullscreen and then arranging your subviews on the same slightly-larger-than-the-screen boundaries.

#define kViewFrameWidth 330; // i.e. more than 320

CGRect scrollFrame;
scrollFrame.origin.x = 0;
scrollFrame.origin.y = 0; 
scrollFrame.size.width = kViewFrameWidth;
scrollFrame.size.height = 480;

UIScrollView* myScrollView = [[UIScrollView alloc] initWithFrame:scrollFrame];
myScrollView.bounces = YES;
myScrollView.pagingEnabled = YES;
myScrollView.backgroundColor = [UIColor redColor];

UIImage* leftImage = [UIImage imageNamed:@"ScrollTestImageL.png"];
UIImageView* leftView = [[UIImageView alloc] initWithImage:leftImage];
leftView.backgroundColor = [UIColor whiteColor];
leftView.frame = CGRectMake(0,0,320,480);

UIImage* rightImage = [UIImage imageNamed:@"ScrollTestImageR.png"];
UIImageView* rightView = [[UIImageView alloc] initWithImage:rightImage];
rightView.backgroundColor = [UIColor blackColor];
rightView.frame = CGRectMake(kViewFrameWidth * 2,0,320,480);

UIImage* centerImage = [UIImage imageNamed:@"ScrollTestImageC.png"];
UIImageView* centerView = [[UIImageView alloc] initWithImage:centerImage];
centerView.backgroundColor = [UIColor grayColor];
centerView.frame = CGRectMake(kViewFrameWidth,0,320,480);

[myScrollView addSubview:leftView];
[myScrollView addSubview:rightView];
[myScrollView addSubview:centerView];

[myScrollView setContentSize:CGSizeMake(kViewFrameWidth * 3, 480)];
[myScrollView setContentOffset:CGPointMake(kViewFrameWidth, 0)];

[leftView release];
[rightView release];
[centerView release];

Apologies if this doesn't compile, I tested it in a landscape app and hand edited it back to portrait. I'm sure you get the idea though. It relies on the superview clipping which for a full screen view will always be the case.

Related Topic