引言
最近在做一个 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布局时的差别
首先
在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 ̄)づ (嘿嘿嘿放假了!)