在给iPhone应用做翻页功能的时候,很多时候需要页面无限循环。例如,你有一个小的画册要显示,你想要滑过所有内容,然后从最后一个可以滑到开始那个。用户可以继续滑动只要他们想滑,在一个视图的内容同一个方向可以一直滑动。 这里有两个思路可以做到这个效果:

重复最后的视图

第一个观点对小型的循环是最好的方法。假设你有十张图片要显示。当用户在第一张图片的时候要向左滑动,会让用户看到第十张图片。当用户在第十张图片的时候向右滑动,让用户看到第一张。这里的逻辑需要我们把图片按顺序的添加进来,同时在第一张图片的左边加一张第十张的图片,在第十张的图片右边加一张第一张的图片。

示例图片

现在,当用户滚动到尽头,我们把UIScrollView的偏移量重新定位一下。通过放置一个同样的图片在最后并且不使用动画把偏移量重新定位,让用户有无缝连接的体验。

- (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];    
    }
}

只有三张图片

有时候你想要一个无限循环的页面,但你不想加载很多的内容。例如,在UIScrollView里面你有很多内容要显示。这种情况下,加载大量的数据就不是很理想的方式了。 这时候的逻辑就是保持UIScrollView里就是三个页面。每一个页面都会加载数据,而用户一直看的时候中间的页面加载的内容。当用户滚到到一个新的页面,每一个页面的内容都会被重置,并且偏移量会回到中间的页面,用户正在看的页面。这种做法即使你有大量的数据要滚动,都不会同时加载。同一时间只会加载三张图片。

- (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];
}

原文:http://iosdevelopertips.com/user-interface/creating-circular-and-infinite-uiscrollviews.html

下载源码 Xcode Project – Circular UI Scrollview