UITableViewcell autolayout下动态高度

项目中最经常使用的一个UI就是UITableView了。iOS7、8进一步优化了复用机制,用起来相当爽。配合Autolayout,适配工作减轻了非常多。

曾经做适配工作都是在heightForRow里边先计算出来Cell的高度。然后再CellForRow写适配代码。工作量尽管不是非常大,可是非常繁琐。

相对于这样的写法,假设减去计算height这步,工作量自然降低非常多。首先给出一种我媳妇给提供的方法,这是她做聊天UI时因为过度计算而怒创的方法UITableViewcell autolayout下动态高度,当时我看到就震惊了,之后我就一直用这种方法UITableViewcell autolayout下动态高度

UITableViewcell autolayout下动态高度

f=watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvR3Jvd2luZ0dpYW50/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center.jpg" alt="">

使用这中方法就可以省反复计算frame的操作,计算一次布局就可以。

如今IOS7、8都出来这么久了,autolayout也炒的非常热。如今看了下确实方便了非常多。比我在iOS6方便多了。

前两天看了下autolayout,如今结合tableviewcell试试效果。看了几个demo,发现iOS7跟iOS8不一样,iOS8更加简单。

第一、iOS7 tableviewcell + autolayout

使用storyboard简单创建一个project。并加入例如以下约束(不熟悉约束加入方法的可參考我之前的博客autolayout)

UITableViewcell autolayout下动态高度

关联project文件,Cell连线,复用标识符等(不熟悉。可參考我之前的博客):

UITableViewcell autolayout下动态高度

f=watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvR3Jvd2luZ0dpYW50/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center.jpg" alt="">

UITableViewcell autolayout下动态高度

重头戏来了,代码中改怎样改动:

cellForRow依旧是我们之前的写法,赋值:

<span style="color:#993399;">- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TestCell *cell = [tableView dequeueReusableCellWithIdentifier:@"testCell" forIndexPath:indexPath];
NSLog(@"cell create...");
if (!cell) {
NSLog(@"cell is nil!");
}
cell.ts_label.text = self.data[indexPath.row]; return cell;
}</span>

重点在于计算height,改动方法例如以下:

<span style="color:#993399;">- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
TestCell* cell = [tableView dequeueReusableCellWithIdentifier:@"testCell"]; cell.ts_label.text = self.data[indexPath.row];
CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
NSLog(@"size = %@ %lf",NSStringFromCGSize(size), cell.ts_label.preferredMaxLayoutWidth
); return size.height + 1;
}
</span>

&#8;&#8;有三点须要注意:

第一点:不要在heightForRow使用

- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath

你会发现进入了死循环。heightForRow->cellforRow->hei...Row

第二点:使用systemLayoutSizeFittingSize,他会依据约束条件算出来新的size,(所以约束条件一定要准确,非常多BUG都是由于约束有问题)

它有两种參数:

UIKIT_EXTERN const CGSize UILayoutFittingCompressedSize NS_AVAILABLE_IOS(6_0);//紧凑,大小适中的最小尺寸

UIKIT_EXTERN const CGSize UILayoutFittingExpandedSize NS_AVAILABLE_IOS(6_0);//宽松

第三点:新的size计算的是contentview的size,Cell.size.height = content view.size.height+1,记得加上一个切割线的高度。

好的到这里看看执行效果:

UITableViewcell autolayout下动态高度

咋一看感觉效果实现了,细致观察发现label的高度算的不正确。第三行label不仅仅有三行,所以这个size算的不准。

经过研究发现,这个时候须要给label一个宽度值,这样才干算出来所须要的高度。

能够设置label的这个属性来固定宽度。

// Support for constraint-based layout (auto layout)

// If nonzero, this is used when determining -intrinsicContentSize for multiline labels

@property(nonatomic) CGFloat preferredMaxLayoutWidth NS_AVAILABLE_IOS(6_0);

我们改动heightForRow的方法:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
TestCell* cell = [tableView dequeueReusableCellWithIdentifier:@"testCell"];
cell.ts_label.preferredMaxLayoutWidth = 260;
cell.ts_label.text = self.data[indexPath.row];
CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
NSLog(@"size = %@ %lf",NSStringFromCGSize(size), cell.ts_label.preferredMaxLayoutWidth
); return size.height + 1;
}

跑起来看看效果:

UITableViewcell autolayout下动态高度

f=watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvR3Jvd2luZ0dpYW50/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center.jpg" alt="">

这才像个样子,哇哈哈。

这个属性也能够在storyboard中设置:

UITableViewcell autolayout下动态高度

第二、iOS8 tableviewcell + autolayout

iOS7的方法已经简单非常多了,只是iOS8更加简单:iOS8仅仅须要两行代码加上约束就可以完毕适配!

UITableViewcell autolayout下动态高度有木有非常夸张!!

看方法:

<span style="color:#993399;">- (void)viewDidLoad {
</span><span style="color:#663366;"> [super viewDidLoad]; self.data = @[@"hahahahahahahahahahahaha",@"gagagaga",@"lalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalala",@"wawawawawawawawawawawawawawawawawawawawa",@"papapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapa",@""];
self.tableView.estimatedRowHeight = 120;
self.tableView.rowHeight = UITableViewAutomaticDimension; }</span>
<span style="color:#663366;">- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TestCell *cell = [tableView dequeueReusableCellWithIdentifier:@"testCell" forIndexPath:indexPath];
NSLog(@"cell create...");
if (!cell) {
NSLog(@"cell is nil!");
}
cell.ts_label.text = self.data[indexPath.row]; return cell;
}</span>

看到没有,iOS8设置都不须要heightForRow了。仅仅须要设置下预估高度

<span style="color:#663366;">estimatedRowHeight</span>
<span style="color:#663366;"></span><pre name="code" class="objc"><span style="color:#663366;">rowHeight = UITableViewAutomaticDimension</span>

iOS7优化了tableview,获取Cell高度不再是一次性所有载入heightForRow。然后再生成Cell。而是先调用:

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath

等Cell真正要呈现的时候在调用heightForRow。

真实的效果呢

UITableViewcell autolayout下动态高度

高端大气上档次啊,哇哈哈。

看看其它机型

UITableViewcell autolayout下动态高度

哈哈,就是这么简单,Cell就是配好了!

!!

总结一下:iOS7须要注意preferredMaxLayoutWidth的设置,iOS8须要设置estimatedRowHeight、rowHeight = UITableViewAutomaticDimension。更加注意的是约束的准确!

!。UITableViewcell autolayout下动态高度

上一篇:hdoj上的一题和程序设计第二次作业的拓展-人见人爱a+b


下一篇:iOS开发出错whose view is not in the window hierarchy!的解决