一、前言
前段時(shí)間來了一個(gè)新設(shè)計(jì)蝌焚,將App的風(fēng)格修改了一遍迟螺。在顯示文字時(shí)赶掖,增加了行間距。原本以為只是展示和計(jì)算高度的時(shí)候添加上富文本的lineSpace屬性即可达箍,但是結(jié)果在顯示一行中文的時(shí)候没龙,卻怎么也計(jì)算字體的時(shí)候多了一個(gè)行間距的高度,展示的Label也多了一個(gè)行間距的高度缎玫。經(jīng)過查找資料硬纤,網(wǎng)上也有人遇到同樣的坑。計(jì)算高度時(shí)赃磨,需要將判斷一下是否中文與一行筝家,如果是一行帶中文并且有行間距,此時(shí)總體高度應(yīng)該減去行間距邻辉。展示的Label如果用的是自適應(yīng)高度溪王,也應(yīng)該做一下判斷,一行中文帶行間距時(shí)值骇,不設(shè)置Label的lineSpace屬性莹菱。如果你也遇到這樣坑,可以通過本文章的Demo解決吱瘩,并封裝好一些方法道伟,便于以后的使用。
二搅裙、文本獲取高度的方式:
通常計(jì)算文本的高度使用以下兩種方式皱卓,通過計(jì)算出來的高度計(jì)算父控件的總高度裹芝。
通過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];
三、中文富文本有行間距的坑:
計(jì)算文字高度的坑:
以上兩種計(jì)算方式在計(jì)算帶有中文嫂易,并且有行間距的富文本時(shí)兄朋,會(huì)出現(xiàn)在計(jì)算一行時(shí),文本高度不對(duì)怜械,多了一個(gè)行間距的高度颅和。但在計(jì)算純英文時(shí)卻不會(huì)存在這個(gè)情況。這樣會(huì)導(dǎo)致在存在父控件時(shí)缕允,父控件整體高度計(jì)算不對(duì)峡扩。
Paste_Image.png
給Label設(shè)置文本的坑:
在給Label設(shè)置富文本時(shí),如果是一行并且?guī)е形恼媳荆⑶以O(shè)置了間距l(xiāng)ineSpace教届,結(jié)果多發(fā)現(xiàn)顯示出來多了一個(gè)間距的高度响鹃。
Paste_Image.png
四、解決方案:
計(jì)算文字高度的坑:
判斷行數(shù)與是否存在中文案训,當(dāng)行數(shù)為一行买置,并且存在中文時(shí),需要將計(jì)算結(jié)果的高度減去行間距强霎。此時(shí)才為正確文本正確高度忿项。
給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
五、封裝與使用(便于以后的使用)
對(duì)NSString進(jìn)行以下方法的增加家夺。
/**
- 計(jì)算文字高度怕膛,可以處理計(jì)算帶行間距的
*/
- (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;
}
/*
- 計(jì)算最大行數(shù)文字高度,可以處理計(jì)算帶行間距的
*/
-
(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;
}
}
/**
- 計(jì)算是否超過一行 用于給Label 賦值attribute text的時(shí)候 超過一行設(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;
}
}