美文网首页
ScrollView转TableView

ScrollView转TableView

作者: Johnny_Wu | 来源:发表于2018-10-25 09:41 被阅读0次

把ScrollView转TableView,难点应该在cell复用的实现。下面重点讲解这部分的实现。

一、定义基本变量

    //_visiblePages:存当前正在显示的cell,
    //_recycledPages:存回收的cell
    NSMutableSet *_visiblePages, *_recycledPages;
    //firstIndex:当前显示中第一个cell的索引
    //lastIndex:当前显示中最后一个cell的索引
    NSInteger firstIndex;
    NSInteger lastIndex;

二、复用代码的实现

//复用函数
- (void)tilePages
{
    NSInteger num = [self.myDelegate numOfTableView:self];
    firstIndex = (NSInteger)floorf(CGRectGetMinY(self.bounds)/_cellHeight);
    lastIndex = (NSInteger)floorf((CGRectGetMaxY(self.bounds)-1)/_cellHeight);
    if(firstIndex<0)
        firstIndex = 0;
    if(firstIndex>num-1)
        firstIndex = num - 1;
    if(lastIndex<0)
        lastIndex = 0;
    if(lastIndex>num-1)
        lastIndex = num - 1;
    
    //回收
    for(MyTableViewCell *page in _visiblePages)
    {
        if(page.index<firstIndex||page.index>lastIndex)
        {
            [_recycledPages addObject:page];
            [page removeFromSuperview];
        }
    }
    
    [_visiblePages minusSet:_recycledPages];
    while (_recycledPages.count > 2) // Only keep 2 recycled pages
        [_recycledPages removeObject:[_recycledPages anyObject]];
    
    //添加新的page
    for(NSInteger index = firstIndex;index<=lastIndex;index++)
    {
        //如果不在显示队列中,就加入新的cell
        if(![self isDisplayingPageForIndex:index])
        {
            MyTableViewCell *page = [self dequeueRecyclePage];
            if(!page)
            {
                page = [[MyTableViewCell alloc] init];
                NSLog(@"创建新的page%ld",index);
            }
            [_visiblePages addObject:page];
            //重新设置page的位置
            [self configurePage:page forIndex:index];
            
            if([self.myDelegate respondsToSelector:@selector(MyTableView:willDisplayCell:forIndex:)])
            {
                [self.myDelegate MyTableView:self willDisplayCell:page forIndex:index];
            }
            
            [self addSubview:page];
        }
    }
    
}

- (MyTableViewCell *)dequeueRecyclePage
{
    MyTableViewCell *page = [_recycledPages anyObject];
    if(page)
        [_recycledPages removeObject:page];
    
    return page;
}
- (BOOL)isDisplayingPageForIndex:(NSInteger)index {
    for (MyTableViewCell *page in _visiblePages)
        if (page.index == index) return YES;
    return NO;
}

- (void)configurePage:(MyTableViewCell *)page forIndex:(NSInteger)index {
    page.frame = CGRectMake(0, _cellHeight*index, self.bounds.size.width, _cellHeight);
    page.index = index;
}

大体思路如下:
1、计算出firstIndex和lastIndex,用这个来确定每次显示cell的索引范围。
2、进行回收:判断显示数组_visiblePages中的每个cell,如果发现不在前面的索引范围的,都从数组中移除,并放入到回收数组_recycledPages中。
3、为了防止回收数组过大,这里控制了回收数组最多存在两个cell。
4、复用或创建新的cell:在索引firstIndex和lastIndex范围间的,但不存在_visiblePages中的cell,都是必须进行复用或创建。回收数组如果还有cell,就直接复用,如果没有,就得创建新的cell。把新的cell添加到_visiblePages中,并把这个cell调整为正确的位置。
5、在每次滑动scrollView的时候,都重复执行上面的复用函数。

我只是进行了一个简单的实现,包括每个cell的高度我都定死了,复用只用于同一类型的cell。当然你们可以在这个基础上进行拓展,把它实现得跟系统的UITableView类似。

代码地址:https://github.com/wulang150/ScrollToTable

相关文章

网友评论

      本文标题:ScrollView转TableView

      本文链接:https://www.haomeiwen.com/subject/xwfqtqtx.html