最近公司需要修改主界面,把以前所有服务类型都统一类型显示改为分模块化显示。也就造成以前用一个collectionView解决的事情,需要使用到UITableViewCell给不同类型的服务分组。每一个cell中的服务个数又不确定,只能TableViewCell种嵌套UICollectionView。
步骤 1. 使用xib来定义一个cell,用UICollectionView来填充这个cell, 使用上下左右约束来根据不同高度的collectionView 撑起这个cell.
步骤2. 在xib中设置UICollection的属性,如 scroll Direction 设置为Vertical 垂直显示。 Scrolling Enable设置为NO。
在代码中设置属性
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;
遇到的问题。
- 刷新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问题后,首次刷新时,UICollectionViewCell的宽高度设置来撑起CollectView高度的预期值不一样。造成有一个动画显示。
解决方法:在tableViewCell中给UICollectionViewCell赋值时,在前面添加下面两行代码就OK,提前刷新一下tableViewCell.
//下面这两个语句一定要添加,否则第一屏显示的collection view尺寸,以及里面的单元格位置会不正确
cell.frame = tableView.bounds;
[cell layoutIfNeeded];