關(guān)于行間距l(xiāng)ineSpacing

步驟一:行間距 lineSpacing

先貼出一張 iOS 中 UILabel 的默認(rèn)排版樣式:

UILabel默認(rèn)排版樣式

大家也都能看出來,默認(rèn)的排版樣式中,文本的行間距很小,顯得文本十分?jǐn)D亭畜。

這種時候,設(shè)計師就會提出行間距的需求,希望讓文本展示得更美觀扫尺。類似的標(biāo)注就會像這樣:

設(shè)計師的要求

通常來說既然設(shè)計師要求的是行間距,那么我們直接設(shè)置 lineSpacing 就好炊汤。但是 UILabel 是沒有這么一個直接暴露的屬性的正驻,想要修改 lineSpacing,我們需要借助 NSAttributedString 來實現(xiàn)抢腐,示意代碼:

NSMutableParagraphStyle*paragraphStyle=[NSMutableParagraphStylenew];paragraphStyle.lineSpacing=10;NSMutableDictionary*attributes=[NSMutableDictionarydictionary];[attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];label.attributedText=[[NSAttributedStringalloc]initWithString:label.text attributes:attributes];

運行一下觀察效果:

設(shè)置lineSpacing后

雖然用我們的眼睛看上去好像沒什么問題姑曙,但是設(shè)計師的火眼金睛一下就能看出來,和設(shè)計稿要求的有差距:

差距對比

怎么會成這樣B醣丁伤靠?這跟說好的不一樣對不對!啼染?不要慌宴合,我來細(xì)細(xì)解釋下焕梅。

正確的實現(xiàn)行間距

先看示意圖:

細(xì)節(jié)示意圖

紅色區(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];paragraphStyle.lineSpacing=10-(label.font.lineHeight-label.font.pointSize);NSMutableDictionary*attributes=[NSMutableDictionary dictionary];[attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];label.attributedText=[[NSAttributedString alloc]initWithString:label.text attributes:attributes];

觀察一下效果争便,完美契合:

修改后效果

步驟二:行高 lineHeight

如果你只關(guān)心 iOS 設(shè)備上的文本展示效果级零,那么看到這里就已經(jīng)夠了。但是我需要的是 iOS 和 Android 展現(xiàn)出一模一樣的效果滞乙,所以光有行間距是不能滿足需求的奏纪。主要的原因在前言也提到了,Android 設(shè)備上的文字上下默認(rèn)留白(上一節(jié)圖中藍(lán)色和紅色重疊的部分)和 iOS 設(shè)備上的是不一致的:

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),示意代碼:

NSMutableParagraphStyle*paragraphStyle=[NSMutableParagraphStyle new];paragraphStyle.maximumLineHeight=lineHeight;paragraphStyle.minimumLineHeight=lineHeight;NSMutableDictionary*attributes=[NSMutableDictionary dictionary];[attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];label.attributedText=[[NSAttributedString alloc]initWithString:label.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凰荚,希望知道的老司機指點一二)燃观。最終的代碼示例如下:

NSMutableParagraphStyle*paragraphStyle=[NSMutableParagraphStyle new];paragraphStyle.maximumLineHeight=lineHeight;paragraphStyle.minimumLineHeight=lineHeight;NSMutableDictionary*attributes=[NSMutableDictionary dictionary];[attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];CGFloat baselineOffset=(lineHeight-label.font.lineHeight)/4;[attributes setObject:@(baselineOffset)forKey:NSBaselineOffsetAttributeName];label.attributedText=[[NSAttributedString alloc]initWithString:label.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 啊<摹浇雹?坑爹呢這是!屿讽?

好在我們通常是行高和行間距針對不同的需求分別獨立使用的昭灵,它們在分開使用時不會觸發(fā)這個問題。所以在 VirtualView-iOS 庫中伐谈,我暫且將高度計算的邏輯保持和系統(tǒng)一致了烂完。

參考:?http://www.reibang.com/p/a0390f70ea36

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市诵棵,隨后出現(xiàn)的幾起案子抠蚣,更是在濱河造成了極大的恐慌,老刑警劉巖履澳,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘶窄,死亡現(xiàn)場離奇詭異,居然都是意外死亡距贷,警方通過查閱死者的電腦和手機护侮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來储耐,“玉大人,你說我怎么就攤上這事滨溉∈蚕妫” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵晦攒,是天一觀的道長闽撤。 經(jīng)常有香客問我,道長脯颜,這世上最難降的妖魔是什么哟旗? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上闸餐,老公的妹妹穿的比我還像新娘饱亮。我一直安慰自己,他們只是感情好舍沙,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布近上。 她就那樣靜靜地躺著,像睡著了一般拂铡。 火紅的嫁衣襯著肌膚如雪壹无。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天感帅,我揣著相機與錄音斗锭,去河邊找鬼。 笑死失球,一個胖子當(dāng)著我的面吹牛岖是,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播她倘,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼璧微,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了硬梁?” 一聲冷哼從身側(cè)響起前硫,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎荧止,沒想到半個月后屹电,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡跃巡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年危号,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片素邪。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡外莲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出兔朦,到底是詐尸還是另有隱情偷线,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布沽甥,位于F島的核電站声邦,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏摆舟。R本人自食惡果不足惜亥曹,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一邓了、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧媳瞪,春花似錦骗炉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至龙巨,卻和暖如春笼呆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背旨别。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工诗赌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人秸弛。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓铭若,卻偏偏與公主長得像,于是被迫代替她去往敵國和親递览。 傳聞我的和親對象是個殘疾皇子叼屠,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355