美文网首页iOSiOS 开发
tableViewCell 中嵌套 CollectionView

tableViewCell 中嵌套 CollectionView

作者: 左燈右荇丶 | 来源:发表于2016-08-17 21:30 被阅读11063次

引言

最近在做一个 App 是视频类的 初步做出来的效果:

初步效果图
就是上面这样··(表示图好大)

在试了几种方法最后,选择了用在tableViewCell 中嵌套 CollectionView的方法。

须知

1.得先清楚CollectionView创建的步骤(非xib)

因为是在要嵌套到tableViewCell 里边创建 所以 代理是必须的

<UICollectionViewDataSource,UICollectionViewDelegate>

定义布局对象也是必须的

    //创建布局对象
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];

之后就是初始化collectView和布局对象

 //创建集合视图(需要布局对象进行初始化)
    self.collectView = [[UICollectionView alloc] initWithFrame:[UIScreen mainScreen].bounds collectionViewLayout:layout];

布局(以下只是一部分还有很多 不一一赘述)

    //确定item的大小
    layout.itemSize = CGSizeMake(100, 120);
    
    //确定横向间距
    layout.minimumLineSpacing = 10;
    
    //确定纵向间距
    layout.minimumInteritemSpacing = 10;
    
    //确定距离上左下右的距离
    layout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
    

    
    //头尾部高度
    layout.headerReferenceSize = CGSizeMake(10, 10);
    layout.footerReferenceSize = CGSizeMake(10, 10);
    
        //确定滚动方向
    layout.scrollDirection = 0;

设置代理也是必须的

        //设置集合视图代理
    self.collectView.delegate = self;
    self.collectView.dataSource = self;

把CollectionView 放到 cell上

    [self addSubview:self.collectView];

以上内容写在自定义的cell中的

//注册方法1
    [self.tableView registerNib:[UINib nibWithNibName:@"   " bundle:nil] forCellReuseIdentifier:@" "];
//写在cell的
- (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
}

//注册方法2
    [self.tableView registerClass:<#(nullable Class)#> forCellReuseIdentifier:<#(nonnull NSString *)#>]
//在cell重写一个初始化方法
//  在分配数据前 调用

之后就是代理方法了 (必须的两个)

//元素个数
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    return 0;
}
//数据分配
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@" " forIndexPath:indexPath];
    
    
    return cell;
}

tableViewCell使用xib布局时的差别

首先

xib图
在tableViewCell.xib上拖入CollectionView
这里与纯代码的差别是:
不需要在自行设置 布局对象UICollectionViewFlowLayout
宽高 上下左右间隔都可以在边调动 很直观
cell size 设置宽高
section lnsets 设置与边框间隔
min spacing 设置元素间隔

但使用起来不能达到真正的自适应
屏幕宽度改变(6和6plus) 因为设死了元素的宽 所以间隔会不一样
而且设置的数值与真实数值有偏差 如果使用元素宽自适应cell高度时会有问题
ps:在这种状态下也是需要设置代理的

MVC 模式下的传值

简单效果图

从最开始的tableViewController 开始
一开始收到的数据大概是这样的

[
{
    "titel":2013
    "itmes":[
             {data}
             ]
}
{
    "titel":2011
    "itmes":[
             {data},
             {data},
             {data},
             {data},
             {data}
            ]
}
]

先把每一年的东西打包放入数组

        NSArray *arr = [{
    "titel":2013
    "itmes":[
             {data}
             ]
}
{
    "titel":2011
    "itmes":[
             {data},
             {data},
             {data},
             {data},
             {data}
            ]
}]

//创建Model 继承NSObject
//在.h中设置对应属性
@property (nonatomic, strong) NSDictionary *items;
//网络请求需要在.m加
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
    
}
        for (NSDictionary *dic in arr) {
//装进model
            Model *model = [[ScreeningTableModel alloc] init];
            [model setValuesForKeysWithDictionary:dic];
//所有model放入数组
            [self.dataArr addObject:model];
        }

//分配数据

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//对应cell 的.h文件里要吧 Model写成属性
//@property (nonatomic, strong) Model *model;
    XMVarietyScreeningTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"screening" forIndexPath:indexPath];
    
//调用 model的set方法 每次调用都会传值
    cell.model = self.dataArr[indexPath.row];
    
    return cell;
}

自定义model的set方法 (tableViewCell中)
- (void)setModel:(Model *)model{
    if (_model != model) {
        _model = model;
        每次调用都会接收到值
        //收到的是一个年份的数据
        //self.model.items 里边有对应年的times里的数据
//初始化数组 tableViewCell里的每次都要初始化
 self.dataArr = [NSMutableArrayy array];
                for (NSDictionary *dic in self.model.items) {
  // 这样每个元素的信息都会装到数组里
//装进model2 
            Model2 *model = [[ScreeningTableModel alloc] init];
            [model setValuesForKeysWithDictionary:dic];
//所有model放入数组
            [self.dataArr addObject:model];
                 }
  //多个tableView 需要收到数据后需要刷新CollectionView
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.CollectionView reloadData];
        });
          }
    }

//分配到CollectionViewCell
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    XMStarShowCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"show" forIndexPath:indexPath];
       cell.model = self.dataArr[indexPath.row];
    return cell;
}

//CollectionViewCell cell上的分配 这里也是最后的地方了 把得到的数据放到对应的控件上就好了 O(∩_∩)O~~
- (void)setVariety:(StarItmes *)variety{
    if (_variety != variety) {
        _variety = variety;
        //封面图片
        [self.imageView sd_setImageWithURL:[NSURL URLWithString:self.variety.images[@"poster"][@"url"]]];
        //封面信息
        self.timeL.text = self.variety.hint[@"left"];
        //片名
        self.titelL.text = self.variety.title;
        self.introL.text = self.variety.sub_title;
    }
}

当然这样的效果是没有自定义tableViewCell的高度 没法像上边那个图一样tableViewCell的高度不一样
自适应高度 :
1.需要做到的就是传值 , 你需要计算有多少个元素 这么多个元素会占几行 简单的 用 count / 一行的个数计算 或者 用宽来算 (用宽来算比较好看 反正本强迫症是这么认为的 因为能够在所有屏幕上实现自适应 每个的宽 和间隔都 是一样的`` 但要求纯代码 因为XIB布局出来你无法要到精确的间隔宽)
2.需要注意一定要在数据传过来后再算
3.记得刷新tableViewController (在传值时把Controller的地址传过来 不然刷新没用不是同一个东西)
4.tableViewCell太多的时候看不到的cell在你拖动时才开始加载 所以数组需要每次使用前初始化
5.如果以上都做好的 接收数据方面没有出现问题 然后在分配CollectionViewCell数据是总是崩溃出现数组越界的提示在

//这个地方     
  cell.model = self.dataArr[indexPath.row];

这是在自适应tableViewCell高度后会出现的 东西一多就会 改变高度时tableView需要刷新 接收数据时tableViewCell中的CollectionView需要刷新 所以滑动tableView时就出现了问题(具体表示懵逼 ) 所以在确认传过来的数据没有错的情况下可以直接用

 //就是这么粗暴
    if (indexPath.row < self.itemArr.count) {
          cell.model = self.dataArr[indexPath.row];
    }

表示如果有大神路过可以科普一下····

16年 8月17日 随笔········

(@ο@) 哇~ 我又诈尸了!
声明几点东西吧~
1、因为工作原因没弄iOS的Ui好久了 现在mvvm我都没得看过 原生SDK和底层接口倒是看了不少!以前的项目早交了 也没有时间弄 所以呢demo是么有的了~
2、我看了蛮多留言的,现在还需要这个东西的朋友给你们指指路 好好去看 UITableView重用机制 和 用UICollectionView实现瀑布流
3、像什么UITableView需要返回主线程刷新呀 都是蛮基础的了 新学的朋友多碰到几次多问问度娘就知道了,写这东西都是去年的事了 现在回来看感觉跟不上时代了~
4、要元旦了! 大家新年快乐? (づ ̄ 3 ̄)づ (嘿嘿嘿放假了!)

相关文章

网友评论

  • Hello_kid:把CollectionView 放到 cell上 这里不应该是[self.contentview addSubview:self.collectionview]
  • 只因为趁年轻:嵌套好几个collectionview 会卡顿,楼主有什么好的解决办法吗?
  • 贾代表:如果你的collectionView 里的 cell的大小都不固定,不能确定count呢
    贾代表:@左燈右荇丶 关于计算不固定大小类型的这种问题,用到了其它解决途径
    贾代表:@左燈右荇丶 哦,问题已经解决
    左燈右荇丶:count不能确定? 为什么? 这个不是服务器传给你的数据决定的嘛? 你吧JSON数据转换后赋给对应Model 把这些model放到 数组里边 数组的个数不就是cell 的count了吗 cell大小不固定是什么意思 你们美术效果图就要求 每个装内容的容器要不一样大小嘛?如果是感觉是要你做一个瀑布流的效果 你可以去查一下 collectionView 瀑布流 的实现 这篇东西知识点两个tableview的重用机制 和collectionView 中cell的适应布局 屏幕长宽 都是有接口可以取到的 其他间距 边距全部可以写成变量 cell的大小一般就是自定义写好 不然就是资源决定,比如说图片 你拿到你就能求它的尺寸
  • 走着走着就会敲代码了:来回滚动,看过内存吗 会一直增加吗?
  • 布袋的世界:cell.layoutIfNeed
  • 崠崠:这种布局 直接用collectionView来实现不就好了吗。。。。。这么嵌套的话 不觉得更麻烦吗
    厚脸皮小强打不死的小强:你得考虑下整个界面肯定还有其他的分组:relaxed:
  • Bales_chu:我也是 tableView 里的 cell 里放了一个 collectionView ,我想问一下怎么把你从网络请求下来的数据数组传给 tableView ,需要这个数组的 count 来算tableViewCell 的高度
  • 115ccb264d5e:这样有坑啊 如果一直刷新 里边的collectionView高度提前算好 就做不到复用 因为cell相当于一直在屏幕上面没有进入缓存池 数据超过一定程度 内存受不了 就闪退了 考虑一下
    115ccb264d5e:@小多多最后没有用嵌套 直接把头部的视图放在collectionView的头部 直接用他自己的复用 最好不要用嵌套 容易出现坑
    小多多:我遇到这个问题,有没有解决方案呀
  • 香橙柚子:你好,我早tableViewcell里面嵌套collectionView,但是collectionView的cell最前面的两个获取不到数据,要刷新才能获取到.也就是往后滚,再滑滚回来的时候才能有数据.这怎么解决
    香橙柚子:@左燈右荇丶 已经好了,谢谢
    左燈右荇丶:@iOS_xuanhe 你要确定数据是拿到了没显示还是没请求到
    左燈右荇丶:@iOS_xuanhe 在主线程刷新你的table
  • 0937ce57381c:w我做的嵌套,加载数据有问题
    Mr_liRookie:有什么问题?我现在没什么问题,就是画面不是很流畅,性能有待优化
  • LD_左岸:我现在tableViewCell上加了一个collectionView 把tableViewCell设置为collectionView的数据源代理 在我上下拖动tableView时 cell里的collectionView的数据源代理方法 并没调用 然而collectionView上的item就是没有了 item是用xib描述的 里面只有一张imageView 请大神点拨
  • 95608a08c8ee:我在做tableviewcell嵌套collectionview 的时候遇到一个问题,大概效果如微博,含0-9张图片。

    我在tableviewcell中定义了一个model来储存cell中的数据,其中包含了collectionviewcell中的图片数据和文字等。

    但在显示数据的时候,就只有collection view中的图片出错了。比如tableview:cell1~cell9,分别有1~9张图片,但是cell9只有1张或者2张。。。model中images对应的位置出错了,但是collectionview 中images的count和其他数据没错。然后出现collectionview下标越界,collectionview 中格式错误

    请问知道是什么问题吗?
    嘴爷:@DragonYang 试了下,还是不行
    95608a08c8ee:@嘴爷 如果是这个问题的话,在tableview中的cellForRowAtIndexPath加入[collectionView reloadData]应该就可以了。http://blog.csdn.net/dragonryo/article/details/59657708
    嘴爷:@DragonYang 我也碰到了,把这个应用在朋友圈里,行不通啊
  • 夜生物:大神,有一个tableView三个分区, 第三个分区里面有一个collectionview,如何确定第三个分区的高度?
    夜生物:@ChineseTiger 我用的xib做的,collectionview的item不固定,在tableviewcontroller获取的数据,然后把模型传给了collectionview,结果总是多出来一些空白的地方,不清楚怎么回事:sweat: 大神有demo吗?参考一下:smile:
    左燈右荇丶:@ChineseTiger 这样说吧! 一个分区就是最底层的tableView中的一个Cell(你应该注意我每个区都有区头吧 。其实设置好需要几个区 然后每个区只要一个cell就好)设置高度其实就是设置所用的cell的高度 。是第区的cell 在设置的时候做判断就好
  • 8530c394d791:我是想知道点击collectionview上面的cell以后,怎么用push跳转,因为collection view是嵌套在tableview的cell里面的,所以只能用present,但是我想push怎么办.......
    左燈右荇丶:@8530c394d791 你要先保证你的东西在导航栏控制器底下才能用push(因为我需求是点击图片才跳转 点到文字不跳 所以并没有设cell的跳转方法 不清楚你的情况 )。
    左燈右荇丶:@8530c394d791 点击collectionview上面的cell 触发的是collectionview上的cell的点击方法 在设置collectionview的.m文件里 设置就好 。还有我这个collectionview的cell里分别有UIButton(放图片 所以直接伙直接设置了按钮的点击方法 没有设Cell的点击) 和 uilabel。
  • 8530c394d791:我是想知道点击collectionview上面的cell以后,怎么用push跳转,因为collection view是嵌套在tableview的cell里面的,所以只能用present,但是我想push怎么办.......
  • 8530c394d791:我是想知道点击collectionview上面的cell以后,怎么用push跳转,因为collection view是嵌套在tableview的cell里面的,所以只能用present,但是我想push怎么办.......
  • 8530c394d791:我是想知道点击collectionview上面的cell以后,怎么用push跳转,因为collection view是嵌套在tableview的cell里面的,所以只能用present,但是我想push怎么办.......
    哭与行:代理,通知,block,根控制器
    莦婼姑娘:在cell里写个block,参数写你想要传的东西,collectionview的代理方法点击的时候调这个block,这样应该可以实现,具体还要你试试
    Mr_liRookie:利用代理和代码块都是可以实现的
  • 小白我们走吧:那应该怎么做自适应高度的呢 :pensive:
    小白我们走吧:@左燈右荇丶 那能让它根据collection view 的内容来返回么
    左燈右荇丶:@小白我们走吧 根据你需要放的内容计算(算的时候别写死 把数据放进数组然后用他的count 算) 然后把数值返回到tableView 用设置cell高度的方法设置 。 要清楚逻辑 最底层的是tableview 所以他的cell的高度决定后面能显示多少

本文标题:tableViewCell 中嵌套 CollectionView

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