优化——UIScrollView通过内容延迟加载以达到平滑滑动。

前面写了一篇《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
代码非常简单,很容易理解,如有更好的方法或者意见,欢迎指点。

你可能感兴趣的:(iOS)