UIScrollView 平滑划动处理
原文链接,请支持原作者:http://blog.csdn.net/gavinming/article/details/6745988
?iOS开发经常会用到UIScrollView,而能够平滑的展示划动效果,是至关重要的。比较常用的方法有两种:
? ? ? 1)将所有的scrollview子页面都add到scrollview中,这样可以平滑滑动,但占用资源加多,并且初始化加载比较慢。
? ? ? 2)使用三个页面View,在滑动过程中如指针轮询那样交替使用。优点是占用内存少,但如果单个页面比较大,经常会在划动到中间位置的时候,出现卡顿,很影响用户体验性。
?
? ? ? 第一种方法就不多讲解,如果页面不多,并且每个页面加载的资源也比较少,那么建议采用第一种方式。如果页面比较多,资源比较大,则建议采用延迟加载的方式。
?
?更优的方法,请查看:《优化——UIScrollView通过内容延迟加载以达到平滑滑动。》
? ? ? 现在UIScrollView使用有两种方法:一种是App Dev里面的Sample,建立一个包含页面数据的数组,划动的同时,不断添加和删除其他页。而另外一种是定义三个页面,划动过程中,类似与木板搭桥过河游戏一样,prev->current->next->prev,只需重新加载新载入的页面。
1、创建UIScrollView和三个自定义的View:
?
[cpp]?view plaincopy- ????//***********************************UIScrollView***********************************/??
- ????scrollView?=?[[UIScrollView?alloc]?initWithFrame:CGRectMake(0,?54,?TOP_BIG_IMAGE_WIDTH,?TOP_BIG_IMAGE_HEIGHT)];??
- ????scrollView.autoresizingMask?=?UIViewAutoresizingFlexibleWidth;??
- <span?style="white-space:pre">????</span>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进行更新操作的代码。
?
[cpp]?view plaincopy- 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];??
- ??
- oint?offset?=?CGPointMake(currentPage?*?self.scrollView.frame.size.width,?0);??
- [self.scrollView?setContentOffset:offset?animated:NO];??
2、在- (void)scrollViewDidScroll:(UIScrollView *)sender方法中进行页面更新。
?
?
[cpp]?view plaincopy- #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是页面的更新操作判断。
?
?
[cpp]?view plaincopy- -?(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];??
- }??