iOS開發(fā)中經(jīng)常需要根據(jù)字符串的數(shù)量和字體大小來計算UILabel的高度。
系統(tǒng)為我們提供了兩種方法:
1.NSString和NSAttributedString的boundingRectWithSize方法
2.UIView的sizeThatFits方法
這兩種方法使用起來很簡單,但是有不少坑要填。
先來看第一種方法
計算下面這個string的size,并且限制label最多展示兩行
NSString *str = @"從她分享的照片和貼文中不難看出對警察工作的熱愛從她分享的照片和貼文中不難看出對警察工作的熱愛";
CGSize size = [str boundingRectWithMaxSize:maxSize font:bigFont maxLineNumber:2];
// NSString category
- (CGSize)boundingRectWithMaxSize:(CGSize)maxSize
font:(UIFont *)font
maxLineNumber:(NSUInteger)maxLineNumber{
if (font==nil || self==nil) {
return CGSizeZero;
}
CGRect rect = [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];
if (maxLineNumber>0){
CGFloat maxHeight = maxLineNumber * font.lineHeight;
if (rect.size.height > maxHeight){
return CGSizeMake(rect.size.width, maxHeight);
}
}
return rect.size;
}
有時還要添加行間距
這就要用到NSMutableAttributedString
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.lineSpacing = 4; //行間距
NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:str];
[attrStr addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, attrStr.length)];
[attrStr addAttribute:NSFontAttributeName value:bigFont range:NSMakeRange(0, attrStr.length)];
CGRect rect = [attrStr boundingRectWithMaxSize:maxSize font:bigFont maxLineNumber:2];
這樣行間距高度就計算出來了。
但是這并沒結(jié)束场绿。
當(dāng)文字比較少,只有一行的時候,你會看到這樣:
Label文字下方多了一段空白高度菊值。沒錯,這就是你剛才設(shè)置的行間距(純英文字符不會有這個問題育灸,只要字符串中包含中文就會這樣腻窒,系統(tǒng)對中文的支持還是不到位)
這就需要我們在字符串只有一行的時候減去行間距:
CGRect rect = [self boundingRectWithSize:maxSize options:options context:nil];
if ((rect.size.height - font.lineHeight) <= lineSpacing && [self.string containsChinese]) {
rect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height-lineSpacing);
}
這樣就完美了嗎?高興的太早了磅崭。
當(dāng)我設(shè)置文字的截斷模式的時候又出問題了
style.lineBreakMode = NSLineBreakByTruncatingTail;
label.numberOfLines = 2;
label.attributedText = attStr;
雖然label行數(shù)設(shè)置為2儿子,但是計算粗來的高度只有一行!
原來當(dāng)你設(shè)置NSLineBreakByTruncatingTail的時候砸喻,NSAttributedString的boundingRectWithSize方法只會按照一行來計算高度柔逼。
NSLineBreakByClipping, NSLineBreakByTruncatingHead, NSLineBreakByTruncatingTail, NSLineBreakByTruncatingMiddle
這幾種LineBreakMode都是這樣
怎么辦呢?
很簡單割岛,不要為NSAttributedString設(shè)置LineBreakMode愉适,在UILabel上設(shè)置這個屬性:
label.lineBreakMode = NSLineBreakByTruncatingTail;
現(xiàn)在算是完美了吧?
不知道癣漆。目前已經(jīng)滿足我們的需求了儡毕。以后遇到坑再填吧。
第二種方法跟第一種差不多扑媚,也有上面類似的問題腰湾,按上面的解決方法也可以自己封裝一個工具,這里就不贅述了疆股。