在我們開發(fā)過程中會遇到乞榨,當(dāng)你的文字很大時沮明,會出現(xiàn)下面的現(xiàn)象
此時的代碼如下:
//行間距減去 12 上14
NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init];
paraStyle.lineBreakMode = NSLineBreakByCharWrapping;
//paraStyle.lineSpacing = 20;
//設(shè)置負(fù)數(shù)沒有效果的
//paraStyle.lineSpacing = 5 + 15;
paraStyle.lineSpacing = 0;
paraStyle.alignment = NSTextAlignmentRight;
NSDictionary *attributes = @{NSParagraphStyleAttributeName : paraStyle};
NSMutableAttributedString * astr = [[NSMutableAttributedString alloc] initWithString:self.lab.text attributes:attributes];
NSDictionary *attribute = @{NSForegroundColorAttributeName : [UIColor blackColor], NSFontAttributeName : [UIFont systemFontOfSize:40]};
[astr addAttributes:attribute range:NSMakeRange(0, self.lab.text.length)];
self.lab.attributedText = astr;
此時我設(shè)置的lineSpacing是0本今,但是圖片上的文字間距還是很大闻蛀,怎么改lineSpacing宰僧,都沒有效果材彪,那如何解決這個問題呢?
正確的實現(xiàn)行間距
紅色區(qū)域是默認(rèn)繪制單行文本會占用的區(qū)域琴儿,可以看到文字的上下是有一些留白的(藍(lán)色和紅色重疊的部分)段化。設(shè)計師是想要藍(lán)色區(qū)域高度為 10pt,而我們直接設(shè)置 lineSpacing 會將兩行紅色區(qū)域中間的綠色區(qū)域高度設(shè)置為 10pt造成,這就是問題的根源了显熏。
那么這個紅色的區(qū)域高度是多少呢?答案是 label.font.lineHeight晒屎,它是使用指定字體繪制單行文本的原始行高喘蟆。
知道了原因后問題就好解決了,我們需要在設(shè)置 lineSpacing 時鼓鲁,減去這個系統(tǒng)的自帶邊距:
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
/**zhushi
(lldb) po _moveTipLabel.font.lineHeight
47.734375
(lldb) po _moveTipLabel.font.pointSize
40
*/
paragraphStyle.lineSpacing = 10 - (_moveTipLabel.font.lineHeight - _moveTipLabel.font.pointSize);
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
_moveTipLabel.attributedText = [[NSAttributedString alloc] initWithString:_moveTipLabel.text attributes:attributes];
觀察一下效果蕴轨,完美契合:
關(guān)于行高 lineHeight
如果你只關(guān)心 iOS 設(shè)備上的文本展示效果,那么看到這里就已經(jīng)夠了骇吭。但是我需要的是 iOS 和 Android 展現(xiàn)出一模一樣的效果橙弱,所以光有行間距是不能滿足需求的。主要的原因在前言也提到了,Android 設(shè)備上的文字上下默認(rèn)留白(上一節(jié)圖中藍(lán)色和紅色重疊的部分)和 iOS 設(shè)備上的是不一致的:
左側(cè)是 iOS 設(shè)備棘脐,右側(cè) Android 設(shè)備斜筐,可以看到同樣是顯示 20 號的字體,安卓的行高會偏高一些蛀缝。在不同的 Android 設(shè)備上使用的字體不一樣顷链,可能還會出現(xiàn)更多的差別。如果不想辦法抹平這差別内斯,就不能真正意義上實現(xiàn)雙端一致了蕴潦。
這時候我們可以通過設(shè)置 lineHeight 來使得每一行文本的高度一致,lineHeight 設(shè)置為 30pt 的情況下俘闯,一行文本高度一定是 30pt潭苞,兩行文本高度一定是 60pt。雖然文字的渲染上會有細(xì)微的差別真朗,但是布局上的差別將被完全的抹除此疹。lineHeight 同樣可以借助 NSAttributedString 來實現(xiàn),示意代碼:
CGFloat lineHeight = 20;
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.maximumLineHeight = lineHeight;
paragraphStyle.minimumLineHeight = lineHeight;
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
_lab.attributedText = [[NSAttributedString alloc] initWithString:_lab.text attributes:attributes];
運行一下觀察效果:
在 debug 模式下確認(rèn)了下文本的高度的確正確的遮婶,但是為什么文字都顯示在了行底呢蝗碎?
修正行高增加后文字的位置
修正文字在行中展示的位置,我們可以用baselineOffset 屬性來搞定旗扑。這個屬性十分有用蹦骑,在實現(xiàn)上標(biāo)下標(biāo)之類的需求時也經(jīng)常用到它。經(jīng)過調(diào)試臀防,發(fā)現(xiàn)最合適的值是 (lineHeight - label.font.lineHeight) / 4(尚未搞清楚為什么是除以 4 而不是除以 2眠菇,希望知道的老司機(jī)指點一二)。最終的代碼示例如下:
#pragma mark - 333
CGFloat lineHeight = 20;
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.maximumLineHeight = lineHeight;
paragraphStyle.minimumLineHeight = lineHeight;
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
CGFloat baselineOffset = (lineHeight - _lab.font.lineHeight) / 4;
[attributes setObject:@(baselineOffset) forKey:NSBaselineOffsetAttributeName];
_lab.attributedText = [[NSAttributedString alloc] initWithString:_lab.text attributes:attributes];
貼一下在不同字號和行高下的展示效果:
行高和行間距同時使用時的一個問題
不得不說行高和行間距我們都已經(jīng)可以完美的實現(xiàn)了袱衷,但是我在嘗試同時使用它們時捎废,發(fā)現(xiàn)了 iOS 的一個 bug(當(dāng)然也可能是一個 feature,畢竟不 crash 都不一定是 bug):
著色的區(qū)域都是文本的繪制區(qū)域致燥,其中看上去是橙色的區(qū)域是 lineSpacing登疗,綠色的區(qū)域是 lineHeight。但是為什么單行的文本系統(tǒng)也要展示一個 lineSpacing 跋釉椤7妗?坑爹呢這是0嵩帷荷腊?
好在我們通常是行高和行間距針對不同的需求分別獨立使用的,它們在分開使用時不會觸發(fā)這個問題急凰。so 暫且將高度計算的邏輯保持和系統(tǒng)一致了。
那么本文開頭我提出問題的解決方式如下,親測有效
CGFloat lineHeight = 45;
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.maximumLineHeight = lineHeight;
paragraphStyle.minimumLineHeight = lineHeight;
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
CGFloat baselineOffset = (lineHeight - _lab.font.lineHeight) / 4;
//[attributes setObject:@(baselineOffset) forKey:NSBaselineOffsetAttributeName];
[attributes setObject:@1 forKey:NSBaselineOffsetAttributeName];
_lab.attributedText = [[NSAttributedString alloc] initWithString:_lab.text attributes:attributes];
本文摘自蘋果核
講解行間距抡锈,很詳細(xì)疾忍,僅供學(xué)習(xí)!