tableView动态行高

目录

手写代码和IB处理tableView动态行高

手写代码情况下,需要考虑的方面:

一、label单行与多行的区别

二、手写label背景填充跟着字来是否麻烦?

三、单行情况下,文字带中文,设置行间距,计算出的高度不准确。

备注


tableView是我们常用的控件之一,我们来谈一谈对于其行高的动态设置。

手写代码:

[string boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size

IB:

设定位置,不设定固定高,editor中设置sizeToFit,在heightForRow方法中给cell赋值后调用layoutIfNeeded方法。

(若想背景填充跟着字来,设置label的width的less than最大宽度,字数不足一行的,约束也会自动缩到与label长度匹配)

由于heightForRow会调用多次,在heightForRow中给cell赋值和调用layoutIfNeeded,性能会比较差。

解决方案:

1、根据id缓存每行的高度

2、设置预估行高

方案1、减少了调用cell赋值和layoutIfNeeded,性能相对提升。但是在获取行高的方法里进行了cell的赋值,结构上不合理。

方案2、在固定行高的情况下合适,动态行高的情况由于预估行高和实际行高的不同会出现列表跳动。这样说来,在固定行高的情况下设置预估行高能减少heightForRow的调用,提升性能。

手写和IB的区别:

手写:仅仅是计算;

IB:程序一启动就会全部加载进内存由系统托管,先强制布局然后看占了多大的尺寸。

使用手写代码的时候,有些东西需要考虑一下:

一、label单行与多行的区别

使用NSStringDrawingUsesLineFragmentOrigin

官方文档的描述:

To correctly draw and size multi-line text, pass NSStringDrawingUsesLineFragmentOrigin in the options parameter.

多行文本draw或者获取高度,需要有NSStringDrawingUsesLineFragmentOrigin在options参数中

我看到有不少人使用了NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading

不明白为什么要这样使用?先看看官方文档对两个选项的描述:

NSStringDrawingUsesLineFragmentOrigin

The specified origin is the line fragment origin, not the base line origin

指定的原点是行片段的原点, 而不是基线原点。

NSStringDrawingUsesFontLeading

Uses the font leading for calculating line heights

使用字体行距计算行高。

我看到文章有提出

1、NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading这种能解决有时高度不准的问题

2、在textView中,显示行数是10行,使用NSStringDrawingUsesLineFragmentOrigin时只计算出了5行的高度,而使用NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading计算出了10行的高度

针对这两个情况:

1、目前我使用中文、英文和中英文混合,使用NSStringDrawingUsesLineFragmentOrigin和使用NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading的效果一样。

2、我通过UIFont获取字高度,textView显示了多少行,算出这几行的高度,然后这些文字通过boundingRectWithSize:options: attributes: context:方法计算一下高度,发现使用NSStringDrawingUsesLineFragmentOrigin没问题。

UIFont中找到了两个属性:ascender、capHeight。第一个可以得到中文字体的实际显示大小,第二个可以得到英文字母和数字的实际显示大小

这样看来使用要不要NSStringDrawingUsesFontLeading都一样,如果有不同的意见,请在下方评论。

二、刚刚看IB背景填充跟着字数来好像很简单,那么手写label背景填充跟着字来是否麻烦?

使用attributedText即可,好像也不麻烦。

三、单行情况下,文字带中文,设置行间距,计算出的高度不准确。

那么看看我们需要先确定的判断条件:

1、是否设置行间距;

2、是否是单行;

3、是否带中文;

tableView动态行高_第1张图片

那么如果满足这三种情况的话,我将size高度中的lineSpacing减掉不就可以了,那么看代码

tableView动态行高_第2张图片

这个时候运行后会发现还是有问题,size对了,但是label设置attributedText时带了lineSpacing,字的显示不对,那么我需要将attributedText中的lineSpacing也去掉。


tableView动态行高_第3张图片

这个时候没问题了。以上方法都放在NSString+Private文件中。

备注:

官方文档:

This method returns fractional sizes (in the size component of the returned CGRect); to use a returned size to size views, you must raise its value to the nearest higher integer using the ceil function.

获取的CGRect的值用一下ceil方法

你可能感兴趣的:(tableView动态行高)