iOS --UIlabel insert

via:http://mp.weixin.qq.com/s/3xWoaNcTQKnJDZoG1KrcAg
1瘟栖、需求

不知道大家是否常有這樣的需求:一個界面中,有多個 view蜡豹,每個 view 的大小由其內(nèi)容決定麸粮。當(dāng)一個 view 有內(nèi)容時,下一個 view 與它之間會一個間隔镜廉。如果沒有內(nèi)容的話弄诲,下一個 view 就會緊挨著它。如下圖所示:
[圖片上傳中娇唯。齐遵。。(1)]
圖1 中塔插,四個 label 的大小是自適應(yīng)的梗摇,且每個 label 相隔 10px。這種情況下想许,視圖看起來是很正常的伶授。但如果其中某些 label 沒有文字呢?看下圖:


[圖2] label2.text = nil

[圖3] label2.text = nil; label3.text= nil;

圖2 是 label3.text 為 nil流纹,中間有一個明顯過大的間隔糜烹,這是由于 label3 的高度雖然為 0,但由于它與 label2 的間隔為 10px漱凝,而 label4 與它的間隔又是 10px疮蹦,所以造成了圖中 label2 與 label4 的過大的間隔。
圖3 則更為慘不忍睹碉哑。
這時挚币,咱們的需求就出來了:label 與 label 之間的間隔能隨著它們自身內(nèi)容的變化而變化。當(dāng)有文本時扣典,間隔存在妆毕;當(dāng)沒有文本時,則緊挨在一起贮尖。當(dāng)然笛粘,這里的間隔希望不僅是垂直的,水平方向也應(yīng)該是一樣的湿硝。
2薪前、解決方案

來看看各種解決方法。
2.1 動態(tài)更新約束

這是最直觀关斜、容易想到的辦法示括,就是在 label2 等內(nèi)容有變化時,去調(diào)整相關(guān)的間隔約束:更改 constants 或 優(yōu)先級 等痢畜。
這種方法存在的問題是維護成本太高垛膝,這里只有四個 label ,但是要維護這種間隔約束關(guān)系主就已經(jīng)很累了丁稀。所以這種方法是比較初級的吼拥,不靈活。
2.2 -(CGSize)intrinsicContentSize

自定義-(CGSize)intrinsicContentSize


視圖的 內(nèi)容 在 auto layout 中线衫,其與約束是 同樣重要的凿可。視圖有一個方法:– (CGSize)intrinsicContentSize,用來返回展示完整視力內(nèi)容的最小 size授账。
比如 UILabel 就是根據(jù)它的 text枯跑、attributedText 和 preferredMaxLayoutWidth 等來計算出它的內(nèi)容 size。
當(dāng)視圖內(nèi)容改變時矗积,可以調(diào)用 – (void)invalidateIntrinsicContentSize 方法來讓 Auto Layout 在下次布局時重新計算全肮。
咱們可以將間隔當(dāng)作 內(nèi)容 的一部分,將其計算在內(nèi):
<pre>
@interface NLLabelIntervalView : UIView
@property (nonatomic, strong) UILabel *label;
@property (nonatomic, assign) CGSize intervalSize;
@end
@implementation NLLabelIntervalView

  • (CGSize)intrinsicContentSize {
    CGSize size = [self.label intrinsicContentSize];
    if ([self.label.text length] > 0) {
    size.width += self.intervalSize.width;
    size.height += self.intervalSize.height;
    }
    return size;
    }
    @end
    </pre>
    可以看到棘捣,這種方法在一定程度上可以解決間隔問題辜腺,但它有很大的不足:它將間隔 侵入 到內(nèi)容中;需要 包裝 目標(biāo)視圖乍恐,這個代價卻實在有點大评疗,雖然利用 繼承 可以一部分 包裝 問題,但類似于這里的 UILabel茵烈,由于它內(nèi)容的繪制方法(文字垂直居中)百匆,繼承 是無法做到 間隔 的。不過在自定義視圖時呜投,如果就間隔考慮進去的話加匈,問題倒是不大存璃。
    所以,這種方案適用于自定義視圖中雕拼,對系統(tǒng)定義的視圖幫助有限纵东。
    2.3 利用對齊矩形(alignment rect)

你可能會直觀的認(rèn)為 Auto Layout 中,約束是使用 frame 來確定視圖的大小和位置的啥寇,但實際上偎球,它使用的是 對齊矩形(alignment rect) 這個幾何元素。不過在大多數(shù)情況下辑甜,frame 和 alignment rect 是相等的衰絮,所以你這么理解也沒什么不對。
系統(tǒng)有 frame 不用磷醋,為啥要用 alignment rect 呢猫牡?
有時候,咱們在創(chuàng)建復(fù)雜的視圖時邓线,可能會添加各種裝飾元素镊掖,如陰影、外邊框褂痰、角標(biāo)等等亩进。但考慮到開發(fā)這樣的視圖所需時間成本,或者為了避免離屏渲染等原因缩歪,會找設(shè)計師直接切相應(yīng)的成品圖給咱們归薛。如下圖:
alignment rect
[圖片上傳中。匪蝙。主籍。(4)](圖片來源:iOS Auto Layout Demystified)

上圖中,(a) 是咱們拿到的圖逛球,(c) 是這個圖的 frame千元。顯然,咱們在布局的時候颤绕,不想將陰影和角標(biāo)考慮進去(視圖的 center 和 底邊幸海、右邊都發(fā)生了偏移),而是只考慮中間的核心部分奥务,如圖 (b) 中框出的矩形所示物独。
對齊矩形就是用來處理這種情況的。
UIView 提供了方法氯葬,由 frame 得到 alignment rect:
// The alignment rectangle for the specified frame.

  • (CGRect)alignmentRectForFrame:(CGRect)frame;

它得可逆挡篓,也就是說得能從 alignment rect 反過來得到 frame:
// The frame for the specified alignment rectangle.

  • (CGRect)frameForAlignmentRect:(CGRect)alignmentRect;

考慮到每次重寫這兩個方法比較煩,系統(tǒng)也提供了一個簡便方法帚称,由 inset 來指定 frame 與 aligment rect 的關(guān)系:
// The insets from the view’s frame that define its alignment rectangle.

  • (UIEdgeInsets)alignmentRectInsets;

回到間隔問題官研。咱們可以將間隔當(dāng)作上面提到的裝飾秽澳,讓 UILabel 的 alignment rect 比 frame 多個 10 point 間隔就好了:
<pre>
@interface NLLabel : UILabel
@end
@implementation NLLabel

  • (UIEdgeInsets)alignmentRectInsets {
    return UIEdgeInsetsMake(.0, .0, -10.0, .0);
    }
    </pre>

不過讓人感覺迷惑是的,在 iOS 中戏羽,frameForAlignmentRect: 和 alignmentRectForFrame: 重寫之后肝集,并沒有起到預(yù)期的作用,OS X 中倒是正常蛛壳。所以在 iOS 中,還是使用 alignmentRectInsets 的好所刀。對于這個現(xiàn)象衙荐,還希望有了解的同學(xué)幫忙解釋一下。
當(dāng)然浮创,每次都得要繼承才能使用對齊矩形忧吟,畢竟不太方便,也許 關(guān)聯(lián)對象 和 method swizzled 組合起來是個可行方案:
<pre>

import <objc/runtime.h>

@interface UIView (nl_aligmentRectInsets)
@property (nonatomic, copy) UIEdgeInsets (^nl_alignmentRectInsets)(UIEdgeInsets originInsets);
@end
...
</pre>
3 總結(jié)

對齊矩形可是個好玩意呢~
參考:
1斩披、Apple Developerhttps://developer.apple.com/reference/uikit/uiview?language=objc
2溜族、Advanced Auto Layout Toolboxhttp://www.objc.io/issue-3/advanced-auto-layout-toolbox.html
3、iOS Auto Layout Demystified

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末垦沉,一起剝皮案震驚了整個濱河市煌抒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌厕倍,老刑警劉巖寡壮,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異讹弯,居然都是意外死亡况既,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門组民,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棒仍,“玉大人,你說我怎么就攤上這事臭胜∧洌” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵耸三,是天一觀的道長榜配。 經(jīng)常有香客問我,道長吕晌,這世上最難降的妖魔是什么蛋褥? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮睛驳,結(jié)果婚禮上烙心,老公的妹妹穿的比我還像新娘膜廊。我一直安慰自己,他們只是感情好淫茵,可當(dāng)我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布爪瓜。 她就那樣靜靜地躺著,像睡著了一般匙瘪。 火紅的嫁衣襯著肌膚如雪铆铆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天丹喻,我揣著相機與錄音薄货,去河邊找鬼。 笑死碍论,一個胖子當(dāng)著我的面吹牛谅猾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鳍悠,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼税娜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了藏研?” 一聲冷哼從身側(cè)響起敬矩,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蠢挡,沒想到半個月后谤绳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡袒哥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年缩筛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堡称。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡瞎抛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出却紧,到底是詐尸還是另有隱情桐臊,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布晓殊,位于F島的核電站断凶,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏巫俺。R本人自食惡果不足惜认烁,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧却嗡,春花似錦舶沛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至撼港,卻和暖如春坪它,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背帝牡。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工往毡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人否灾。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像鸣奔,于是被迫代替她去往敵國和親墨技。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,562評論 2 349

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