一、前言
前段時間來了一個新設(shè)計怜庸,將App的風(fēng)格修改了一遍当犯。在顯示文字時,增加了行間距割疾。原本以為只是展示和計算高度的時候添加上富文本的lineSpace屬性即可嚎卫,但是結(jié)果在顯示一行中文的時候,卻怎么也計算字體的時候多了一個行間距的高度宏榕,展示的Label也多了一個行間距的高度拓诸。經(jīng)過查找資料,網(wǎng)上也有人遇到同樣的坑担扑。計算高度時恰响,需要將判斷一下是否中文與一行,如果是一行帶中文并且有行間距涌献,此時總體高度應(yīng)該減去行間距胚宦。展示的Label如果用的是自適應(yīng)高度,也應(yīng)該做一下判斷,一行中文帶行間距時枢劝,不設(shè)置Label的lineSpace屬性井联。如果你也遇到這樣坑,可以通過本文章的Demo解決您旁,并封裝好一些方法烙常,便于以后的使用。
二鹤盒、文本獲取高度的方式:
通常計算文本的高度使用以下兩種方式蚕脏,通過計算出來的高度計算父控件的總高度。
- 通過UILabel sizeThatFits獲取文本的高度
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 1)];
label.font = [UIFont systemFontOfSize:14]; label.numberOfLines = 0; label.attributedText = attributeString;
CGSize size = [label sizeThatFits:CGSizeMake(label.frame.size.width, CGFLOAT_MAX)];
NSLog(@"size:%@", NSStringFromCGSize(size));
NSLog(@"label.frame.size:%@", NSStringFromCGSize(label.frame.size));
- boundingWithRect
NSString *text = @"恰同學(xué)少年侦锯,風(fēng)華正茂";
NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:text];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init]; style.lineSpacing = 10;
[attributeString addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, text.length)];
[attributeString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:14] range:NSMakeRange(0, text.length)]; NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading;
CGRect rect = [attributeString boundingRectWithSize:CGSizeMake(100, MAXFLOAT) options:options context:nil];
三驼鞭、中文富文本有行間距的坑:
- 計算文字高度的坑:
以上兩種計算方式在計算帶有中文,并且有行間距的富文本時尺碰,會出現(xiàn)在計算一行時挣棕,文本高度不對,多了一個行間距的高度亲桥。但在計算純英文時卻不會存在這個情況洛心。這樣會導(dǎo)致在存在父控件時,父控件整體高度計算不對题篷。
Paste_Image.png
- 給Label設(shè)置文本的坑:
在給Label設(shè)置富文本時词身,如果是一行并且?guī)е形模⑶以O(shè)置了間距l(xiāng)ineSpace悼凑,結(jié)果多發(fā)現(xiàn)顯示出來多了一個間距的高度偿枕。
Paste_Image.png
四、解決方案:
- 計算文字高度的坑:
判斷行數(shù)與是否存在中文户辫,當(dāng)行數(shù)為一行渐夸,并且存在中文時,需要將計算結(jié)果的高度減去行間距渔欢。此時才為正確文本正確高度墓塌。 - 給Label設(shè)置文本的坑:
需要判斷是否超過一行,超過一行不設(shè)置富文本的lineSpace奥额。
//文本的高度減去字體高度小于等于行間距苫幢,判斷為當(dāng)前只有1行
if ((rect.size.height - _font.lineHeight) <= paragraphStyle.lineSpacing){
if ([self containChinese:str]) { //如果包含中文
rect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height-paragraphStyle.lineSpacing);
}
}
//判斷如果包含中文
- (BOOL)containChinese:(NSString *)str {
for(int i=0; i< [str length];i++){ int a = [str characterAtIndex:i];
if( a > 0x4e00 && a < 0x9fff){
return YES;
}
}
return NO;
}
Paste_Image.png
五、封裝與使用(便于以后的使用)
對NSString進(jìn)行以下方法的增加垫挨。
/**
* 計算文字高度韩肝,可以處理計算帶行間距的
*/
- (CGSize)boundingRectWithSize:(CGSize)size font:(UIFont*)font lineSpacing:(CGFloat)lineSpacing
{
NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:self];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = lineSpacing;
[attributeString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, self.length)];
[attributeString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, self.length)];
NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading;
CGRect rect = [attributeString boundingRectWithSize:size options:options context:nil];
// NSLog(@"size:%@", NSStringFromCGSize(rect.size));
//文本的高度減去字體高度小于等于行間距,判斷為當(dāng)前只有1行
if ((rect.size.height - font.lineHeight) <= paragraphStyle.lineSpacing) {
if ([self containChinese:self]) { //如果包含中文
rect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height-paragraphStyle.lineSpacing);
}
}
return rect.size;
}
//判斷如果包含中文
- (BOOL)containChinese:(NSString *)str {
for(int i=0; i< [str length];i++){ int a = [str characterAtIndex:i];
if( a > 0x4e00 && a < 0x9fff){
return YES;
}
}
return NO;
}
/**
* 計算最大行數(shù)文字高度,可以處理計算帶行間距的
*/
- (CGFloat)boundingRectWithSize:(CGSize)size font:(UIFont*)font lineSpacing:(CGFloat)lineSpacing maxLines:(NSInteger)maxLines{
if (maxLines <= 0) {
return 0;
}
CGFloat maxHeight = font.lineHeight * maxLines + lineSpacing * (maxLines - 1);
CGSize orginalSize = [self boundingRectWithSize:size font:font lineSpacing:lineSpacing];
if ( orginalSize.height >= maxHeight ) {
return maxHeight;
}else{
return orginalSize.height;
}
}
/**
* 計算是否超過一行 用于給Label 賦值attribute text的時候 超過一行設(shè)置lineSpace
*/
- (BOOL)isMoreThanOneLineWithSize:(CGSize)size font:(UIFont *)font lineSpaceing:(CGFloat)lineSpacing{
if ( [self boundingRectWithSize:size font:font lineSpacing:lineSpacing].height > font.lineHeight ) {
return YES;
}else{
return NO;
}
}