iOS开发经常会用到UIScrollView,而能够平滑的展示划动效果,是至关重要的。比较常用的方法有两种:
1)将所有的scrollview子页面都add到scrollview中,这样可以平滑滑动,但占用资源加多,并且初始化加载比较慢。
2)使用三个页面View,在滑动过程中如指针轮询那样交替使用。优点是占用内存少,但如果单个页面比较大,经常会在划动到中间位置的时候,出现卡顿,很影响用户体验性。
第一种方法就不多讲解,如果页面不多,并且每个页面加载的资源也比较少,那么建议采用第一种方式。如果页面比较多,资源比较大,则建议采用延迟加载的方式。
更优的方法,请查看:《优化——UIScrollView通过内容延迟加载以达到平滑滑动。》
现在UIScrollView使用有两种方法:一种是App Dev里面的Sample,建立一个包含页面数据的数组,划动的同时,不断添加和删除其他页。而另外一种是定义三个页面,划动过程中,类似与木板搭桥过河游戏一样,prev->current->next->prev,只需重新加载新载入的页面。
1、创建UIScrollView和三个自定义的View:
//***********************************UIScrollView***********************************/
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 54, TOP_BIG_IMAGE_WIDTH, TOP_BIG_IMAGE_HEIGHT)];
scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.scrollView.contentSize = CGSizeMake(numberOfPages * self.scrollView.frame.size.width,
self.scrollView.frame.size.height);
self.scrollView.delegate = self;
scrollView.autoresizesSubviews = YES;
scrollView.pagingEnabled = YES;
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.scrollsToTop = NO;
[selfView addSubview:scrollView];
三个自定义View。函数setPageContentWithPageView:(CustomView *)pageView withPageNumber:(NSInteger)pageNumber,是对customview进行更新操作的代码。
prevPageView = [[CustomView alloc] initWithFrame:CGRectMake(0, 0, self.scrollView.frame.size.width,
self.scrollView.frame.size.height)];
currentPageView = [[CustomView alloc] initWithFrame:CGRectMake(0, 0, self.scrollView.frame.size.width,
self.scrollView.frame.size.height)];
nextPageView = [[CustomView alloc] initWithFrame:CGRectMake(0, 0, self.scrollView.frame.size.width,
self.scrollView.frame.size.height)];
CGFloat pageWidth = self.scrollView.frame.size.width;
CGFloat pageHeight = self.scrollView.frame.size.height;
currentPageView.frame = CGRectMake(currentPage * pageWidth, 0, pageWidth, pageHeight);
[self setPageContentWithPageView:currentPageView withPageNumber:currentPage];
//第一页
if (currentPage == 0)
{
prevPageView.frame = CGRectZero;
nextPageView.frame = CGRectMake(((currentPage + 1) * pageWidth), 0, pageWidth, pageHeight);
if (numberOfPages - 1 >= currentPage + 1)
{
[self setPageContentWithPageView:nextPageView withPageNumber:currentPage + 1];
}
}
//最后一页
else if (currentPage == numberOfPages - 1)
{
prevPageView.frame = CGRectMake(((currentPage - 1) * pageWidth), 0, pageWidth, pageHeight);
nextPageView.frame = CGRectZero;
[self setPageContentWithPageView:prevPageView withPageNumber:currentPage - 1];
}
else
{
prevPageView.frame = CGRectMake(((currentPage - 1) * pageWidth), 0, pageWidth, pageHeight);
nextPageView.frame = CGRectMake(((currentPage + 1) * pageWidth), 0, pageWidth, pageHeight);
[self setPageContentWithPageView:prevPageView withPageNumber:currentPage - 1];
[self setPageContentWithPageView:nextPageView withPageNumber:currentPage + 1];
}
[self.scrollView addSubview:currentPageView];
[self.scrollView addSubview:prevPageView];
[self.scrollView addSubview:nextPageView];
CGPoint offset = CGPointMake(currentPage * self.scrollView.frame.size.width, 0);
[self.scrollView setContentOffset:offset animated:NO];
2、在- (void)scrollViewDidScroll:(UIScrollView *)sender方法中进行页面更新。
#pragma mark -
#pragma mark UIScrollViewDelegate Methods
- (void)scrollViewDidScroll:(UIScrollView *)sender
{
CGFloat pageWidth = self.scrollView.frame.size.width;
NSInteger page = floor((self.scrollView.contentOffset.x - pageWidth/2) / pageWidth) + 1;
// 已经是第一页再往向前翻页,或者已经是最后一页再往后翻页。
if (currentPage == page || page < 0 || page >= numberOfPages)
{
return;
}
else
{
//先赋值,防止scrollView在执行线程后还未执行currentPage = page,导致不断进入该段代码区执行
NSInteger prevPage = currentPage;
currentPage = page;
//防止用户快速滑动,出现因线程未加载完,出现空百夜
self.scrollView.userInteractionEnabled = NO;
//线程处理,使得加载动作不会阻塞主线程而出现卡顿。注意,不加afterDelay:0.1,线程会立刻执行,卡顿会出现。
[self performSelector:@selector(refreshPageViewAfterPaged:)
withObject:[NSNumber numberWithInteger:prevPage]
afterDelay:0.1];
}
}
函数refreshPageViewAfterPaged是页面的更新操作判断。
- (void)refreshPageViewAfterPaged:(NSNumber *)prevPageNumber
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
self.scrollView.userInteractionEnabled = YES;
CGFloat pageWidth = self.scrollView.frame.size.width;
CGFloat pageHeight = self.scrollView.frame.size.height;
NSInteger prevPage = [prevPageNumber integerValue];
//页面向后滑动一页
TopPicView *tempPageView = nil;
if (currentPage - 1 == prevPage)
{
tempPageView = currentPageView;
currentPageView = nextPageView;
nextPageView = prevPageView;
prevPageView = tempPageView;
prevPageView.frame = CGRectMake(((currentPage - 1) * pageWidth), 0, pageWidth, pageHeight);
currentPageView.frame = CGRectMake(currentPage * pageWidth, 0, pageWidth, pageHeight);
if (currentPage == (numberOfPages - 1))
{
nextPageView.frame = CGRectZero;
}
else
{
nextPageView.frame = CGRectMake(((currentPage + 1) * pageWidth), 0, pageWidth, pageHeight);
//页面更新操作的实质代码:
[self setPageContentWithPageView:nextPageView withPageNumber:currentPage + 1];
}
}
else if (currentPage + 1 == prevPage)
{
tempPageView = currentPageView;
currentPageView = prevPageView;
prevPageView = nextPageView;
nextPageView = tempPageView;
currentPageView.frame = CGRectMake(currentPage * pageWidth, 0, pageWidth, pageHeight);
nextPageView.frame = CGRectMake(((currentPage + 1) * pageWidth), 0, pageWidth, pageHeight);
if (currentPage == 0)
{
prevPageView.frame = CGRectZero;
}
else
{
prevPageView.frame = CGRectMake(((currentPage - 1) * pageWidth), 0, pageWidth, pageHeight);
[self setPageContentWithPageView:prevPageView withPageNumber:currentPage - 1];
}
}
[pool release];
}