Pages

Tuesday 8 November 2011

Creating Circular and Infinite UIScrollview.

Editor’s Note: This post was written by Jacob Haskins, Director of Mobile Development at Accella. Thanks to Jon Stroz of Accella for reaching out to me to share this idea.
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:
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, You may have a lot of content to display inside the UIScrollView. Loading large amounts of data there would not be the ideal approach to the situation.
The logic that we can use there is to keep the UIScrollView at just three pages. Data would load on each page and the user would always be looking at the data in the middle page. When the user scrolled to a new page, the content for each page would be reset and the offset would go back the user is back to viewing the middle page. That way even though you may have a large amount of data to scroll through, it’s not all loaded at once. Only three pages are ever loaded at one time.
 
- (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];
}

Download the Source Code


0 comments:

Post a Comment

Feel Free to Share your Views