iOS计算Label的最合适的Size

iOS中经常有需要给Label一个最合适的宽度和高度,京东和淘宝的搜索历史就是个典型应用:
iOS计算Label的最合适的Size
文章图片

关于计算方法,以前一直使用的是NSString的一个方法:

- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(nullable NSDictionary *)attributes context:(nullable NSStringDrawingContext *)context API_AVAILABLE(macos(10.11), ios(7.0));

使用的例子如下,这里是想获取合适的宽度,就要给宽度传入一个很大的值,然后高度给一个固定的值:
- (CGFloat)textWidth:(NSString *)text { CGFloat width = [text boundingRectWithSize:CGSizeMake(1000, 30) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil].size.width + 20; return width; }

但是这个方法其实很不准确,所以大多还会在返回的基础上,加一个值,例如上面这个代码就加20,以避免给的宽度过小,导致无法显示完全。
可即使这样做了,返回的这个宽度,我发现仍然有可能偏小,并会引起一些UI问题,例如我在做这个历史搜索界面的时候,就发现有些label,最右面会有一条线,如下所示:
iOS计算Label的最合适的Size
文章图片

我一开始以为是我不小心加了一条线在Label上,结果用xcode查看了视图层级,发现没有其他图层了,我怀疑可能给的这个宽度不对,导致出现的这个问题,我采用了另外的方法,这个是UIView的一个方法,不过宽度不对,导致这条线出现的更深层次的原因,应该是UILabel的实现的问题。

- (CGSize)sizeThatFits:(CGSize)size; // return 'best' size to fit given size. does not actually resize view. Default is return existing view size

官方的注释已经告诉我们这个,这个可以给出最佳的size,使用的时候必须是已经实例化出来的View,比如Label的话,要先初始化,然后赋值text和font,例子如下:
UILabel *contentLabel = [[UILabel alloc] initWithFrame:CGRectZero]; contentLabel.font = [UIFont systemFontOfSize:14]; contentLabel.text = historyArray[i]; CGFloat nowWidth = [self widthForLabel:contentLabel andheight:kSearchHistorySubViewHeight] ...... - (CGFloat)widthForLabel:(UILabel *)label andheight:(CGFloat)height { CGSize sizeToFit = [label sizeThatFits:CGSizeMake(MAXFLOAT, height)]; CGFloat width = sizeToFit.width + 10; return width; }

【iOS计算Label的最合适的Size】这个计算出的宽度确实精确,但都贴着字符的边了,所以我们要加点宽度,不然很不美观。以后label再需要计算精确的宽度或高度,最好用这个方法了。

    推荐阅读