iOS開發(fā)中我們有時需要代碼預(yù)先計算出字符串的寬高來進行特殊布局,在iOS7以后,計算字符串高度使用boundingRectWithSize方法,
- 創(chuàng)建并設(shè)置label控件
UILabel *label = [UILabel new];
label.userInteractionEnabled = NO;
label.textAlignment = NSTextAlignmentCenter;
label.lineBreakMode = NSLineBreakByCharWrapping;
label.numberOfLines = 0;
- 計算字符長度 (一個很長的字符串)
str = @"您邀請\"123\"、\"123\"、...... \"123\"、\"123\"、\"123\"加入了群";
NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:14.0]};
CGSize textRect = CGSizeMake([UIScreen mainScreen].bounds.size.width - 30, MAXFLOAT);
CGFloat textHeight = [str boundingRectWithSize:textRect
options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading
attributes:attributes
context:nil].size.height;
Bug表現(xiàn)
上述的代碼執(zhí)行后就會出現(xiàn)高度計算的問題,實際的效果是顯示的文本高度比計算出來的高度少很多,導(dǎo)致出現(xiàn)空白。
然而當(dāng)我把文本內(nèi)容全都換成中文以后卻變正常了,這讓人摸不著頭腦。
文本換行樣式
- 以單詞為單位換行
label.lineBreakMode = NSLineBreakByWordWrapping;
這種方式將會包含多種規(guī)則
- 英文單詞會作為一個整體不會出現(xiàn)截斷,比如world
- 數(shù)字,例如12345也會作為一個整體
- 各種符號不會出現(xiàn)在行的第一個位置,會將上一行的最后單詞移動到下一行. 包括標點符號和其他符號。例如 ,。, - ' "" _ [ 等等;
- 還有很多規(guī)則,這些都是為了閱讀起來方便;
- 以字符為單位換行
label.lineBreakMode = NSLineBreakByCharWrapping;
這種方式就比較簡單了,以單個字符為單位,如果一行顯示不下則換到下一行,從左到右連續(xù)排版沒有其他規(guī)則;
Bug分析
注意上面代碼part1部分UILabel設(shè)置的是以字符NSLineBreakByCharWrapping為單位換行,而文本計算的時候沒有指定換行方式,系統(tǒng)默認的換行方式是以單詞換行,上面代碼中的數(shù)字123和引號\"還有頓號、都會被換行規(guī)則限定,所以以這種排版計算出來的高度會高很多才導(dǎo)致了這個bug
修正后改后的代碼
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;
NSDictionary * attributes = @{
NSFontAttributeName:font,
NSParagraphStyleAttributeName: paragraphStyle
};
CGSize textRect = CGSizeMake([UIScreen mainScreen].bounds.size.width - 30, MAXFLOAT);
CGFloat textHeight = [str boundingRectWithSize:textRect
options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading
attributes:attributes
context:nil].size.height;