Things a Chameleon Would Say
Web design
When creating paging functionality for iPhone apps, there may be times that an infinite page loop would be desired. For example, if you have a small gallery of photos you are displaying, you may want to swipe through the set and have it start back at the beginning once you reach the end. The user would be able to continue swiping as much as they wanted in one direction to continue to view the content. Here are two strategies for achieving this result:
(UPDATE: Example code below now more extensive and bug free. Example project can be downloaded at end of article.)
Duplicate end caps
The first option is best suited for smaller loops. Suppose you have ten photos to display. When the user is on photo one and swipes left, it will take the user to photo ten. When the user is on photo ten and swipes right, it will take the user to photo one. The logic we will follow here is to add photos in order, but place an duplicate of photo ten to the left of photo one and a duplicate of photo one to the right of photo ten.
Now when the user scrolls to the end, we reposition the content offset of our UIScrollView. By having a duplicate photo at the end and repositioning the offset without using animation, we create a seamless experience for the user.
- (void)scrollViewDidEndDecelerating:(UIScrollView *)sender { // The key is repositioning without animation if (scrollView.contentOffset.x == 0) { // user is scrolling to the left from image 1 to image 10. // reposition offset to show image 10 that is on the right in the scroll view [scrollView scrollRectToVisible:CGRectMake(3520,0,320,480) animated:NO]; } else if (scrollView.contentOffset.x == 3840) { // user is scrolling to the right from image 10 to image 1. // reposition offset to show image 1 that is on the left in the scroll view [scrollView scrollRectToVisible:CGRectMake(320,0,320,480) animated:NO]; } }
3 Pages Only
There may be times when you want an infinite page loop, but don’t want to load in a lot of content. For example, I recently worked on a project that displayed a different document with an image and text for every day of the year. The client wanted an infinite page loop so that the user would be able to scroll through the documents. However, that would be far too much data to load into a UIScrollView all at once. A different approach was needed.
The logic that I used was to keep the UIScrollView at just three pages. A document would load on each page and the user would always be looking at the document in the middle page. When the user scrolled to a new page, the content for each document would be reset and the offset would go back the user is back to viewing the middle page.
- (void)viewDidLoad { [super viewDidLoad]; documentTitles = [[NSMutableArray alloc] init]; // create our array of documents for (int i = 0; i < 10; i++) { [documentTitles addObject:[NSString stringWithFormat:@"Document %i",i+1]]; } // create placeholders for each of our documents pageOneDoc = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 44)]; pageTwoDoc = [[UILabel alloc] initWithFrame:CGRectMake(320, 0, 320, 44)]; pageThreeDoc = [[UILabel alloc] initWithFrame:CGRectMake(640, 0, 320, 44)]; pageOneDoc.textAlignment = UITextAlignmentCenter; pageTwoDoc.textAlignment = UITextAlignmentCenter; pageThreeDoc.textAlignment = UITextAlignmentCenter; // load all three pages into our scroll view [self loadPageWithId:9 onPage:0]; [self loadPageWithId:0 onPage:1]; [self loadPageWithId:1 onPage:2]; [scrollView addSubview:pageOneDoc]; [scrollView addSubview:pageTwoDoc]; [scrollView addSubview:pageThreeDoc]; // adjust content size for three pages of data and reposition to center page scrollView.contentSize = CGSizeMake(960, 416); [scrollView scrollRectToVisible:CGRectMake(320,0,320,416) animated:NO]; } - (void)loadPageWithId:(int)index onPage:(int)page { // load data for page switch (page) { case 0: pageOneDoc.text = [documentTitles objectAtIndex:index]; break; case 1: pageTwoDoc.text = [documentTitles objectAtIndex:index]; break; case 2: pageThreeDoc.text = [documentTitles objectAtIndex:index]; break; } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)sender { // All data for the documents are stored in an array (documentTitles). // We keep track of the index that we are scrolling to so that we // know what data to load for each page. if(scrollView.contentOffset.x > scrollView.frame.size.width) { // We are moving forward. Load the current doc data on the first page. [self loadPageWithId:currIndex onPage:0]; // Add one to the currentIndex or reset to 0 if we have reached the end. currIndex = (currIndex $gt;= [documentTitles count]-1) ? 0 : currIndex + 1; [self loadPageWithId:currIndex onPage:1]; // Load content on the last page. This is either from the next item in the array // or the first if we have reached the end. nextIndex = (currIndex $gt;= [documentTitles count]-1) ? 0 : currIndex + 1; [self loadPageWithId:nextIndex onPage:2]; } if(scrollView.contentOffset.x $lt; scrollView.frame.size.width) { // We are moving backward. Load the current doc data on the last page. [self loadPageWithId:currIndex onPage:2]; // Subtract one from the currentIndex or go to the end if we have reached the beginning. currIndex = (currIndex == 0) ? [documentTitles count]-1 : currIndex - 1; [self loadPageWithId:currIndex onPage:1]; // Load content on the first page. This is either from the prev item in the array // or the last if we have reached the beginning. prevIndex = (currIndex == 0) ? [documentTitles count]-1 : currIndex - 1; [self loadPageWithId:prevIndex onPage:0]; } // Reset offset back to middle page [scrollView scrollRectToVisible:CGRectMake(320,0,320,416) animated:NO]; }
Source Code: http://accella.net/dev/Labs/InfiniteScrollView/InfiniteScrollView.zip
6 Responses to “Objective C – Using a UIScrollView for Infinite Page Loops”
Leave a Reply
Have a Question? Need a Quote?
Drop us a line or give us a call at 888-856-2664
What Our Clients Are Saying
John,
Can I just tell you how impressed I am with your team?! This whole process has been so great and working with you guys has made it SOOOO much easier! Thank you for all your hard work and for convincing us to choose Accella.
SO THRILLED!!
Kubota
Recent Posts
Getting Arrested Can Help Your Business
While generally coming face to face with the law is generally not good for...
Drupal 6 with UberCart / UberPOS - A Love-Hate Relationship?
As most techies and programmers have heard, the Drupal CMS is an extremely...


Thank you very much, Jacob!
This helped me a lot!
great! thanks a lot,jacob
Thanks for this Jacob -
is all that’s required before this to create the UIScrollview in the relevant .XIB, or do I need to add any objects (the three pages / UILabels) in that UIScrollView, and doing this in the .m file does the rest?
Any help much appreciated
James
La Mode Outré – trying to create a photo App for my streetstyle blog and have only managed to create a swipeable NSArray in a UIImageView, but that is a bit cruddy.
great! thank you very much
hi, thnx for such a nice article it helped me a lot to understand how UIScrollView actually works. I further want to enhance the code. currently what im doing I want to nest another scrollview on the parent scroll view at center position. but it is not showing nested scroll view. could you pls help me how to nest scrollview. Regards
Well, that depends on what you mean by ‘it is not showing’. Make sure you frame and contentSize properties are set properly on both parent and nested UIScrollView. Also verify that you are adding both parent and child views to the screen with the appropriate addSubview method.