前面写了一篇《UIScrollView 平滑划动处理》,是通过延迟操作来达到平滑移动,但操作起来比较生涩,而且逻辑较复杂,现在已经弃之不用。
前文已经提到,将所有的内容页全部加入到ScrollView是最简单的方法,而且能够非常平滑划动,但如果是大数据量的时候,明显是不适用的。最近参考了Three20的TTScrollView以及TTPhotoViewController后,终于找到了一种内容页延迟加载的方法,其实iOS设备上的照片浏览就是通过延迟加载的方式实现的,当你快速划动的时候,加载的是缩略图,然后再装入原图。
同样是三页轮转ScrollView.m:
_scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.width, self.view.height)]; _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; _scrollView.backgroundColor = [UIColor clearColor]; _scrollView.contentSize = _scrollView.frame.size; _scrollView.pagingEnabled = YES; _scrollView.delegate = self; [self.view addSubview:_scrollView]; CGRect scrollviewFrame = CGRectMake(0, 0, _scrollView.width, _scrollView.height); _currentPageView = [[ContentView alloc] initWithFrame:scrollviewFrame]; _prevPageView = [[ContentView alloc] initWithFrame:scrollviewFrame]; _nextPageView = [[ContentView alloc] initWithFrame:scrollviewFrame]; [_scrollView addSubview:_prevPageView]; [_scrollView addSubview:_nextPageView]; [_scrollView addSubview:_currentPageView]; _prevPageView.autoresizingMask = _nextPageView.autoresizingMask = _currentPageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
翻页过程中(scrollViewDidScroll),进行必要的即时更新,但这个更新操作必须尽量少,以免影响划动的平滑体验,如加载较小的缩略图。而在翻页后,再通过延时操作载入全部内容进行更新。这样处理后的体验就跟iOS设备上原生的照片App一样,快速划动载入的是缩略图,停顿后则延迟载入正常的图片。
//更新操作 - (void)loadContentView:(ContentView *)contentView withPageIndex:(NSInteger)page isDelay:(BOOL)isDelay { //判断越界 if ((_numberOfPages <= 0)) { return; } Feed *feedData = nil; if (page >= 0 && page < _feedDatas.count) { feedData = [_feedDatas objectAtIndex:page]; } if (feedData != contentView.feedData) { //内容不一致,则调用延迟更新 [contentView loadContentWithFeed:feedData isDelay:isDelay]; } } #pragma mark - #pragma mark UIScrollView - (void)scrollViewDidScroll:(UIScrollView *)scrollView { NSInteger page = floor((_scrollView.contentOffset.x - _scrollView.width / 2) / _scrollView.width) + 1; if (_currentPageIndex == page || page > _numberOfPages - 1 || page < 0) { return; } //换页操作 ContentView *tempPageView = nil; //next page if (_currentPageIndex + 1 == page) { tempPageView = _currentPageView; _currentPageView = _nextPageView; _nextPageView = _prevPageView; _prevPageView = tempPageView; [_nextPageView clearContent]; } //prev page else if (_currentPageIndex - 1 == page) { tempPageView = _currentPageView; _currentPageView = _prevPageView; _prevPageView = _nextPageView; _nextPageView = tempPageView; [_prevPageView clearContent]; } _currentPageIndex = page; _currentPageView.left = _scrollView.width * _currentPageIndex; _prevPageView.right = _currentPageView.left; _nextPageView.left = _currentPageView.right; //即时的更新,如载入缩略图等 } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { if (!decelerate) { [self scrollViewDidEndDecelerating:scrollView]; } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { //延迟更新操作,这里是调用每个页面的延迟更新操作 //这里的更新稍显复杂,如果每个页面只是UIImageView的话,则可直接通过NSTimer延迟载入内容 [self loadContentView:_currentPageView withPageIndex:_currentPageIndex isDelay:YES]; [self loadContentView:_nextPageView withPageIndex:(_currentPageIndex + 1) isDelay:YES]; [self loadContentView:_prevPageView withPageIndex:(_currentPageIndex - 1) isDelay:YES]; }
而页面(ContentView )内部的延迟更新代码则为:
static const NSTimeInterval kContentLoadDelay = 0.5; - (void)loadContentBody { //更新ContentView的延迟内容 //....... [_activityIndicatorView stopAnimating]; } - (void)loadContentDelayed { _loadTimer = nil; [self loadContentBody]; } - (void)startContentLoadTimer:(NSTimeInterval)delay { [_activityIndicatorView startAnimating]; [_loadTimer invalidate]; _loadTimer = [NSTimer scheduledTimerWithTimeInterval:delay target:self selector:@selector(loadContentDelayed) userInfo:nil repeats:NO]; } - (void)loadContentWithFeed:(Feed *)feed isDelay:(BOOL)isDelay { //content相同则退出 if (feed == self.feedData) { return; } //清空content(会同时清空feedData)后赋值 [self clearContent]; self.feedData = feed; if (nil == self.feedData) { return; } [_activityIndicatorView startAnimating]; [self loadContentHeader]; if (isDelay) { //真正的延迟处理 [self startContentLoadTimer:kContentLoadDelay]; } else { [self loadContentBody]; } }
代码示例:http://download.csdn.net/detail/gavinming/4058379
代码非常简单,很容易理解,如有更好的方法或者意见,欢迎指点。