iOS UITableViewCell中包含UICollectionView嵌套 解决UITableViewCell显示异常

转自:https://www.jianshu.com/p/9b03e39b3794

最近公司需要修改主界面,把以前所有服务类型都统一类型显示改为分模块化显示。也就造成以前用一个collectionView解决的事情,需要使用到UITableViewCell给不同类型的服务分组。每一个cell中的服务个数又不确定,只能TableViewCell种嵌套UICollectionView。

步骤 1. 使用xib来定义一个cell,用UICollectionView来填充这个cell, 使用上下左右约束来根据不同高度的collectionView 撑起这个cell.

屏幕快照 2018-06-03 下午3.32.36.png

步骤2. 在xib中设置UICollection的属性,如 scroll Direction 设置为Vertical 垂直显示。 Scrolling Enable设置为NO。

屏幕快照 2018-06-03 下午3.33.17.png

在代码中设置属性

 UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc]init];
    flowLayout.minimumInteritemSpacing = 2.0;
    flowLayout.minimumLineSpacing = 1.0f;
//    flowLayout.itemSize = CGSizeMake(DEVICEWIDTH/4.0-0, DEVICEWIDTH/4.0-8);
//    [flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
    
    //设置代理
    self.collectionView.delegate = self;
    self.collectionView.dataSource = self;
    
//    self.collectionView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
    self.collectionView.backgroundColor = [UIColor whiteColor];
    [self.collectionView registerClass:[NTNewOfficeServicCollectionCell class] forCellWithReuseIdentifier:@"collectionCell"];
    
    [self.collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"reusableView"];

步骤3. 在tableViewCell中设置collectionView 的 dataSource Delegate等。

#pragma mark -- UICollectionDataSource
#pragma mark -- UICollectionViewDataSource
//定义展示的UICollectionViewCell的个数
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return self.serviceListArr.count;
}

//定义展示的Section的个数
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}


//
//每个UICollectionView展示的内容
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    NTNewOfficeServicCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"collectionCell" forIndexPath:indexPath];
    [cell sizeToFit];
    NTSubscribeModel *model = self.serviceListArr[indexPath.row];
    NSString *serViceIconName = [model.iconIOS lastPathComponent];
    NSString *imageName = [[serViceIconName componentsSeparatedByString:@"@3x"] firstObject];
    [cell.imageView downloadImageBycontentUrlStr:model.iconIOS andIsCut:NO placeholdImage:[UIImage imageNamed:[NSString stringWithFormat:@"newOffice_%@",imageName]] options:SDWebImageRefreshCached];
    //SW:  cacheType = SDImageCacheTypeMemory && SDWebImageRefreshCached   内存缓存 && 重新下载刷新缓存, 频繁reloadData 将导致内存持续增加
    cell.textName.text = model.serviceName;
    model = nil;
    return cell;
}


//头部展示的内容
-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView *headView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"reusableView" forIndexPath:indexPath];
    
    return headView;
}

//定义每个UICollectionView 的大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake((DEVICEWIDTH-20-15)/4.0f, DEVICEWIDTH/4.0f-5);
}

//定义每个UICollectionView 的间距
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
    return UIEdgeInsetsMake(5, 10, 5, 10);
}

//每个item之间的间距
- (CGFloat)collectionView:(UICollectionView *)collectionView
                   layout:(UICollectionViewLayout*)collectionViewLayout
minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
    return 2;
}


////动态设置每列的间距大小
//- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
//    return 1.0f;
//}

//
//UICollectionView被选中时调用的方法
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    NTSubscribeModel *model = self.serviceListArr[indexPath.row];
    if(self.newOfficeServiceWasSelect){
        self.newOfficeServiceWasSelect(model, indexPath.row, self);
    }
}

步骤4. 当在tableView中获取到数据时,刷新UitableView , 把需要显示的数据赋值给tableViewCell, 在使用collectionView realoadData, 刷新collectView.

NTNewOfficeServiceCell *cell = [tableView dequeueReusableCellWithIdentifier:NEWIMPORTSERVICECELL forIndexPath:indexPath];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        
        //下面这两个语句一定要添加,否则第一屏显示的collection view尺寸,以及里面的单元格位置会不正确
        cell.frame = tableView.bounds;
        [cell layoutIfNeeded];
        [cell reloadDataWithServiceList:(indexPath.row == 1)?[[self.moduleListDic objectForKey:@"base"] copy]:[[self.moduleListDic objectForKey:@"other"] copy]];
        cell.isShowTitleView = (indexPath.row == 1)?NO:YES;
        
        NTWeakself;
        [cell setNewOfficeServiceWasSelect:^(NTSubscribeModel *subscribModel, NSInteger index, NTNewOfficeServiceCell *unReadCell) {
            NTStrongself;
            [strongself configServiceWasSelect:unReadCell selectIndex:index selectModel:subscribModel];
        }];
        return cell;

遇到的问题。

  1. 刷新tableView时。使用setter方法中刷新collctionView的高度时,UITableViewCell高度不实时更新。

解释: 刚开始是collectionView中赋值时,使用的是直接赋值属性,也就是‘cell.arr = [arr copy]’, 在collection中使用setArr中来赋值,并且刷新collection。本来一行可以显示四个,当赋值四个item的时候,collectionView的contentSize高度会变成两行的高度。导致下一行不显示数据,就是撑过了。
查了一下代码,使用方法赋值后再刷新,就不会出现这个问题。

- (void)reloadDataWithServiceList:(NSArray *)servicetArr {
    if(servicetArr){
        _serviceListArr = servicetArr;
        [self.collectionView reloadData];
      
        //计算collectionView的contentSize的高度,再从新更新collectView的高度约束
        CGFloat height = self.collectionView.collectionViewLayout.collectionViewContentSize.height;
        self.collectionViewConstraint.constant = height;
        [self.collectionView.collectionViewLayout invalidateLayout];
    }
}
  1. 解决1问题后,首次刷新时,UICollectionViewCell的宽高度设置来撑起CollectView高度的预期值不一样。造成有一个动画显示。

解决方法:在tableViewCell中给UICollectionViewCell赋值时,在前面添加下面两行代码就OK,提前刷新一下tableViewCell.

//下面这两个语句一定要添加,否则第一屏显示的collection view尺寸,以及里面的单元格位置会不正确
        cell.frame = tableView.bounds;
        [cell layoutIfNeeded];

小礼物走一走,来简书关注我



作者:淘码小工
链接:https://www.jianshu.com/p/9b03e39b3794
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

猜你喜欢

转载自blog.csdn.net/zhanglizhi111/article/details/86292634