一、计算每行的高度
1.计算每行的高度,它就等于最后这个控件,
如果说,当前这行是有配图的,那么这个行高,就等于这个配图最大的Y值,加上一个margin,
如果说,这行是没有配图的
如果说,这行是没有配图的
那么就等于它正文的最大的Y值,加一个margin,
是不是很简单,
来,咱们试试,
2.计算每行的高度
if(model.picture){
//statements
}
这儿能不能拿到model,是不是拿不到吧,
我们能拿到self.weibo,那个模型吧,
if(self.weibo.picture){
//statement
}
如果它有配图,
if(self.weibo.picture){
//如果有配图,那么行高就等于配图的最大的Y值 + margin
}else{
//如果没有配图,那么行高就等于正文的最大的Y值 + margin
}
//6.计算每行的高度
//在这里,给它声明一个变量
CGFloat rowHeight = 0;
if(self.weibo.picture){
//如果有配图,那么行高就等于配图的最大的Y值 + margin
rowHeight = CGRectGetMaxY(self.imgViewPicture.frame) + margin;
}else{
//如果没有配图,那么行高就等于正文的最大的Y值 + margin
rowHeight = CGRectGetMaxY(self.lblText.frame)+ margin;
}
这样的话,行高是不是就算出来了
那么,你这个行高算出来以后,我们是不是要用这个行高,
怎么来用这个行高呢,
大家回忆一下,还记得如何设置tableView的行高吗,
设置tableView的行高,两种方式吧:
1)tableView.rowHeight = 200 ; 统一设置行高
2)但我们这里显然,每一行的行高,是不是不一样,
每一行的行高不一样,那么这个时候,设置行高,怎么设置,通过一个代理方法来设置吧,
3.通过代理方法,设置行高,
代理方法在哪里,在控制器里,
刚才这是数据源方法吧,再给它来个代理方法
刚才这是数据源方法吧,再给它来个代理方法
再给它来个代理方法
#pragma mark - TableView的代理方法
//返回每行的行高的方法
//这个方法的返回值,还记得吗,CGFloat,这个方法的方法名儿呢,
- (CGFloat)tableView……tableView有一个叫做什么,heightForWorAtIndexPath
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
根据行索引返回每一行的行高
这么一个方法,
那么,现在我的问题来了,
刚才,我们在自定义的Cell里面,计算出了
计算出了行高,现在,我要在控制器里面,拿到这个行高,请问,能拿到吗,
能拿到吗
拿不到,这个时候,怎么办,对,说的非常好,通过代理,
但是,我要告诉你,这里通过代理,是实现不了的,
为什么,理论上就实现不了,
我们这个计算行高,是在什么时候算呢,
是不是在所设置自定义单元格这个set方法里面算的,
给这个自定义单元格这个set模型,
在这个自定义单元格这个set模型方法里面算的行高,
那么,这个方法,这个属性,模型属性这个set方法,在什么时候调用啊,
是不是在这个数据源方法里面,这个时候,才会调这个方法,
才会设置行高的吧,
但是,我要告诉你,这个返回行高的代理方法,
这个返回行高的代理方法,
它会优先于它来先调用,
先调这个方法
再调这个数据源方法
然后后面可能它们会交替调一下,也有可能
也就是说,你是先用行高,然后你才去算的行高,你说你用代理,用什么也不行啊,
来,给大家看一眼吧,看一眼你就感觉到印象深刻一点儿了,
百闻不如一见,
当然你见再多遍,不如你亲手写两遍,
那句话怎么说:“听到的会忘记,看到的会记住,做过的才是你自己的“
我现在在里面,每次都给它返回300,
计算行高,这个方法叫,heightForRowAtIndexPath
这个数据源方法,叫,cellForRowAtIndexPath
这两个方法,咱们看看谁先调用,command + R
是不是先调的heightForRowAtIndexPath
先调的这个方法啊,
这个方法中,是不是要用行高啊,
然后,你是不是才调的计算行高,
是不是这么一个效果,
所以,你说,是不是先调的这个方法
然后才调的上面那个方法,
所以说,你在上面那个方法中,计算行高,
你在上面那个方法中,计算行高,是不是有点儿,为时已晚了吧,
有点儿晚了,
那么,所以说,计算行高,并不难,
关键是,怎么去用这个值吧,
那么,接下来,这个问题,怎么解决呢,这个问题这么来解决,
因为,我们要在这个方法中,用这个行高,
但是,我们是在这个方法中,计算这个行高,
就是,算行高的时候,是不是已经用完了吧,已经晚了,
所以说,既然,你希望在这里去用这个行高,
所以说,一定是在这用行高之前,行高已经算出来了,
算出来以后,然后才能用啊,
所以说,现在解决这个问题的办法就是,把计算行高这个办法,提前算,不要等到在这个数据源方法中,再去算,
在数据源方法中算,就已经晚了,
那把它提前到什么时候算呢,
把它提前到懒加载数据的时候,就来算,行高,
是不是提的很前了,
这个时候,大家可能会问,在懒加载数据的时候,连单元格都没有,怎么算行高呢,
是不是,我们这个单元格,每一个UITableViewCell,在数据源方法中,在这里,才开始创建这个单元格啊,
在数据源方法中,才开始创建单元格,
也就是说,在懒加载数据的时候,这个时候,是不是根本就没有执行这个数据源方法,
是不是单元格都根本就没有吧,
但是没有关系,我们计算,我们现在要做的是什么意思呢,
在懒加载的时候,就把将来这个单元格中,每一个子控件的frame,都算好,
并且,把每一行的行高也算好,
也就是说,当你在这里,当你在这个数据源方法中,拿到这个模型的时候,
这个模型里面,就已经包括了,每一个行的数据模型,以及当前这行的行高,以及当前这个单元格里面所有子控件的frame,
就都算好了,
换句话说,你拿到这个模型,模型里面什么都有了,
模型里面有
1)数据
2)有frame
3)有行高
所有的东西,都有了
你直接用,就OK了,
所以说,就在懒加载的时候,就要把所有的一切,都算好,
那么,要想做到这一切,我们得把刚才的代码,做一个比较大的一个改动,
你不需要新写很多代码,
所以,接下来,我们要做的事情,就是来回的改代码,
不需要新写多少代码,只是需要来回的改代码,
换句话说,大家千万别灰心,咱们刚才辛辛苦苦写的那些算坐标,那些代码,还能用得上,只要把它换个位置,就可以,
既然我们要改代码了,那么,先把现在的代码保留一下吧,
右键,Show in Finder,复制一个副本,
怎么修改呢,注意听,我要的是在懒加载的时候,就把那个模型,就把我们当前每一个子控件的frame,以及行高算出来吧,
但是,大家现在再观察一下,我们这里,
我们这里懒加载的时候,是不是只有这一个模型啊,
这个模型里面,是不是只有这些数据这些属性,
是不是根本没有用来保存frame、和行高那些属性啊,
是不是没有,
我们既然希望在懒加载的时候,就把行高,和每个子控件的frame,都算好,所以说,我们在懒加载的时候,你能把这些值算好,算好的这些值,是不是得保存到一个地方,
是不是得保存到这个模型里面,
所以说,这个时候,这个模型就不够了,我们要在模型里面,除了存储这些数据以外,还得存储每一行的行高,以及每一个子控件的frame,这个值,
所以说,现在这个模型,就不够用了,所以说,我要再创建一个模型,
在这个模型中,既可以保存这些数据,也可以保存行高,也可以保存子控件的frame,
我就是想新建一个模型嘛,对吧,右键,New File,