iOS中文行間距富文本高度與顯示那些坑

一、前言

前段時間來了一個新設(shè)計怜庸,將App的風(fēng)格修改了一遍当犯。在顯示文字時,增加了行間距割疾。原本以為只是展示和計算高度的時候添加上富文本的lineSpace屬性即可嚎卫,但是結(jié)果在顯示一行中文的時候,卻怎么也計算字體的時候多了一個行間距的高度宏榕,展示的Label也多了一個行間距的高度拓诸。經(jīng)過查找資料,網(wǎng)上也有人遇到同樣的坑担扑。計算高度時恰响,需要將判斷一下是否中文與一行,如果是一行帶中文并且有行間距涌献,此時總體高度應(yīng)該減去行間距胚宦。展示的Label如果用的是自適應(yīng)高度,也應(yīng)該做一下判斷,一行中文帶行間距時枢劝,不設(shè)置Label的lineSpace屬性井联。如果你也遇到這樣坑,可以通過本文章的Demo解決您旁,并封裝好一些方法烙常,便于以后的使用。

二鹤盒、文本獲取高度的方式:

通常計算文本的高度使用以下兩種方式蚕脏,通過計算出來的高度計算父控件的總高度。

  1. 通過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));
  1. 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];

三驼鞭、中文富文本有行間距的坑:

  1. 計算文字高度的坑:
    以上兩種計算方式在計算帶有中文,并且有行間距的富文本時尺碰,會出現(xiàn)在計算一行時挣棕,文本高度不對,多了一個行間距的高度亲桥。但在計算純英文時卻不會存在這個情況洛心。這樣會導(dǎo)致在存在父控件時,父控件整體高度計算不對题篷。
Paste_Image.png
  1. 給Label設(shè)置文本的坑:
    在給Label設(shè)置富文本時词身,如果是一行并且?guī)е形模⑶以O(shè)置了間距l(xiāng)ineSpace悼凑,結(jié)果多發(fā)現(xiàn)顯示出來多了一個間距的高度偿枕。
Paste_Image.png

四、解決方案:

  1. 計算文字高度的坑:
    判斷行數(shù)與是否存在中文户辫,當(dāng)行數(shù)為一行渐夸,并且存在中文時,需要將計算結(jié)果的高度減去行間距渔欢。此時才為正確文本正確高度墓塌。
  2. 給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;
    }
}

六九榔、測試項目Demo地址:

https://github.com/casscqt/lineSpaceTextHeightDemo

參考來源:http://www.reibang.com/p/4733af4774ec

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哀峻,一起剝皮案震驚了整個濱河市涡相,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌剩蟀,老刑警劉巖催蝗,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異育特,居然都是意外死亡丙号,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門缰冤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來犬缨,“玉大人,你說我怎么就攤上這事锋谐”槌撸” “怎么了截酷?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵涮拗,是天一觀的道長。 經(jīng)常有香客問我迂苛,道長三热,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任三幻,我火速辦了婚禮就漾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘念搬。我一直安慰自己抑堡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布朗徊。 她就那樣靜靜地躺著首妖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪爷恳。 梳的紋絲不亂的頭發(fā)上有缆,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天,我揣著相機(jī)與錄音温亲,去河邊找鬼棚壁。 笑死,一個胖子當(dāng)著我的面吹牛栈虚,可吹牛的內(nèi)容都是我干的袖外。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼魂务,長吁一口氣:“原來是場噩夢啊……” “哼曼验!你這毒婦竟也來了逆害?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蚣驼,失蹤者是張志新(化名)和其女友劉穎魄幕,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體颖杏,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纯陨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了留储。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翼抠。...
    茶點(diǎn)故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖获讳,靈堂內(nèi)的尸體忽然破棺而出阴颖,到底是詐尸還是另有隱情,我是刑警寧澤丐膝,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布量愧,位于F島的核電站,受9級特大地震影響帅矗,放射性物質(zhì)發(fā)生泄漏偎肃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一浑此、第九天 我趴在偏房一處隱蔽的房頂上張望累颂。 院中可真熱鬧,春花似錦凛俱、人聲如沸紊馏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朱监。三九已至,卻和暖如春暖哨,著一層夾襖步出監(jiān)牢的瞬間赌朋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工篇裁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沛慢,地道東北人。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓达布,卻偏偏與公主長得像团甲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子黍聂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 一躺苦、前言前段時間來了一個新設(shè)計身腻,將App的風(fēng)格修改了一遍。在顯示文字時匹厘,增加了行間距嘀趟。原本以為只是展示和計算高度的...
    俊月閱讀 2,570評論 1 1
  • iOS開發(fā)的過程中,總是避免不了各種高度的自適應(yīng)愈诚,如:UILabel她按、UITextView、UITableView...
    夜?jié)M西樓閱讀 18,337評論 2 48
  • 2017年7月1日晚7炕柔、30下班途中 測試照片 醉生夢死班的趕腳
    楊會江閱讀 162評論 0 0
  • 規(guī)畫:一遍 愛的表達(dá):對孩子表達(dá)愛 自我確認(rèn):我是踐行在路上的心理教練酌泰,我是圓滿具足的。 微笑:10次以上 感恩:...
    馬雙麗閱讀 302評論 0 0
  • 背景說明 最開始接觸美劇是高中的時候匕累,那個時候知道有一部美劇越獄很火陵刹,但是沒條件看。真正意義上看的第一部美劇是天賜...
    sherpur閱讀 588評論 0 49