Autolayout 你理解的夠深刻嗎(1)

Autolayout 中 比如你在某一個視圖里預(yù)留了一個視圖后期是通過代碼創(chuàng)建的視圖需要addSubview上去 則記得先修改原視圖的高度約束的constant,然后再獲取這個原始圖的bounds就能馬上拿到正確的尺寸了或者添加新的視圖,不然就會因為之前默認的xib里的預(yù)留視圖高為0而導(dǎo)致后面addsubview報錯。當然自動布局最大的地方就是約束一定要清晰不沖突,不然就算是各種 setNeedsLayout SetNeedsUpdateConstraints layoutSubviwes layoutIfNeeded 都不起作用 當然你也可以嘗試看看對添加的視圖進行調(diào)用上面的方法,但一般來說只要約束正確了,且操作前就設(shè)置了constant,那就是正確的了。如果遇到幾個不確定的視圖排列一定要顧好各個約束的優(yōu)先級或阻止壓縮或阻止擴張優(yōu)先級,如果intraSize自動算高的之間都不確定又要排列在一起那也可以通過設(shè)置這兩個對象的高為0然后優(yōu)先級為high而不是required,這樣防止在并未設(shè)置預(yù)留視圖的constant前就操作該視圖時導(dǎo)致的編輯器autolayout報錯。

另外在比如在cellForRow里通過對cell設(shè)置model來判斷model邏輯實時Masonry添加移除新的視圖時,該cell其實還沒有被return出去所以此時的cell中操作的xib控件都是獲取的預(yù)先的xib里的值,而不是具體的設(shè)備真實的,這時只能不依賴于當前xib本身的大小進行其他操作了。比如計算label的高度等,而要改用設(shè)備uiscreen上來具體測算。

以constraint為基礎(chǔ)的autolayout設(shè)計允許根據(jù)外部和內(nèi)部大小的改變自動適配尺寸的圖形界面,
外部改變包括:
1 用戶改變window大小(MacOS)
2 用戶進入或離開SplitView分屏(iPad-iOS)
3 設(shè)備旋轉(zhuǎn),想要支持Size-Classes,和不同屏幕尺寸,錄音和電話出現(xiàn)或消失時。
這些變化都可以在RunTime中出現(xiàn)因此需要應(yīng)用支持動態(tài)響應(yīng)這種尺寸的變化,Autolayout正好OK
內(nèi)部改變包括:
1 顯示的內(nèi)容改變
2 支持國際化時(不同語言文字占用空間不同,同語言但各個地區(qū)的格式不同可能帶來的變化,不同語言排版不同比如阿拉伯和希伯來語是從右到左排列)
3 APP支持DynamicType動態(tài)調(diào)整(如動態(tài)改變字體等)

1. 純編碼樣式的設(shè)置frame和position
2. autoresizing mask定義了該如何改變尺寸當父視圖發(fā)生變化時,簡化如何適配外部改變帶來的變化。簡單的OK,復(fù)雜的則需要配合手動編碼。
3. 考慮視圖尺寸不如考慮視圖關(guān)系的Autolayout使用的是constraint約束。關(guān)注基于constraint的size和location。
4. 如果控件是有intrinsic content size則會自動計算好當前內(nèi)容適合的大小無需大小的約束,如果不是則給定了一個默認大小然后通過添加約束保持這個大小。
5. Text Items有一個baseline的屬性,
6. Autolayout的目標就是為視圖之間的關(guān)系創(chuàng)造一個且唯一一個等式。但同時Autolayout也是支持創(chuàng)造不等式(大于 小于)。
7. 根據(jù)優(yōu)先級創(chuàng)建可選約束,1000是必選的,其它都是可選的。所以若要動態(tài)改變優(yōu)先級的約束則不能把要改變的設(shè)置為1000.約束會優(yōu)先從高到低級別滿足。
8. 【CHCR屬性】 UIView and NSView沒有intrinsic size。Sliders在iOS中有自動的width,在MacOS中根據(jù)不同的slider類型有intrinsic高寬。Labels, buttons, switches, and text fields都有intrinsic高寬。Text views 和 imageView高寬可變。intrinsicSize都是基于內(nèi)容的, label or button基于文字多少和字體大小。其它則復(fù)雜點,如圖像為空時則沒有intrinsicSize有則為圖像本身的大小。TextView當可滑動時沒有intrinsicSize,如果不可滑動則根據(jù)是否有寬度來計算其intrinsicSize。Autolayout使用各個維度方向上的約束來闡述intrinsicSize,這個維度的約束就是contentHugging用來把內(nèi)容包圍的剛剛好,和compressionResistance用來把視圖推向外部以防內(nèi)容被剪切。 所以如果未來要設(shè)置的內(nèi)容比現(xiàn)在計算出來的intrinsicSize要長則要設(shè)置其compression的屬性要高了。當然如果你不通過intrinsicSize來確定擁有intrinsicSize的控件足夠的尺寸約束就不再用設(shè)置這兩個屬性了。默認250的抗拉伸和750的抗壓縮使其在內(nèi)容變化時很容易自動擴展拉伸了,只要有可能在Autolayout中優(yōu)先使用intrinsicSize比較好。如果要拉伸一系列的視圖來填充空白,如果不設(shè)置hugging內(nèi)容不超出當前的intrinsicSize還好,超出了又要填充。那誰來填充則要設(shè)置hugging。若hugging屬性(即都保持剛剛好不被強制拉伸)都一樣則Autolayout不知拉伸誰,系統(tǒng)已經(jīng)默認伴我們把label的hugging設(shè)置為了比普通的默認值250高的251所以不擔心label會被拉伸,因為它更能抗拉伸,而他后面的field默認是250則會根據(jù)距父視圖training默默拉伸。但如果前面的label或者后面的field文字超長時,因為label是要優(yōu)先保全自己就會盡量變大到剛剛好顯示全自己就好,不會做多余的拉伸。所以field不斷縮小,但field也有文字也有intrinsicSize,如果label要大到連field的intrinsicSize都不能忍了時,這時就要設(shè)置抗壓縮compressionResistance了減小它則會再次縮小field。所以要達到完美就要既設(shè)置抗拉伸(比如基于當前內(nèi)容的intrinsic,保持hugging高的優(yōu)先顯示,壓縮或拉伸hugging低的。但優(yōu)先級高的控件修改內(nèi)容后根據(jù)intrinsic自動適配后,一旦超過后面控件的intrinsic了就尷尬了,因為后面壓縮不能壓縮到比自己的intrinsicSize還小。)又要設(shè)置抗拉伸(這時,設(shè)置好后面控件的抗壓縮優(yōu)先級底就能壓縮了)。
9. Baseline constraints 只作用于view的intrinsic content height.如果這個view垂直方向上被拉伸或壓縮則這個baseline constraints就不在正確的對齊了。
10. 如果一個view是根據(jù)intrinsic來定的,最好用999來定義優(yōu)先級而不是required。這樣既避免拉伸或壓縮其尺寸的同時也同樣防止特殊情況下的錯誤,因為尺寸錯了也要好過出現(xiàn)錯誤。
11. Autolayout一共提供三種方式設(shè)置約束:views之間control+拖,pin+align工具,xib幫你設(shè)置在自己修改。(當你拖控件到畫布上時,xib自動創(chuàng)建了距離左上角的原版默認隱形約束,這樣直接運行就可以方便調(diào)試,但不要發(fā)布這樣的隱形原型約束app就好了。當你設(shè)置了你第一個約束,系統(tǒng)會自動移除與你約束相關(guān)的那個視圖上的所有原型約束,這樣之后因為沒有足夠的約束導(dǎo)致布局就報錯了。 drag-拖拽方式可以自動識別方向來決定給你的選項是水平還是垂直間距且按住了control控件拖拽也不怕拖歪因為不會強硬改變控件的位置。IB是根據(jù)當前控件的frame來創(chuàng)建約束的,所以拖拽都要大致確定一個位置。另外IB也可以自動幫我們的視圖加約束Resolve Auto Layout Issues tool > Reset to Suggested Constraints.但一般還是滿足不了我們的需求。)
12. intrinsicSize 使用系統(tǒng)默認 如果修改成了placeholder則只在設(shè)計時有build后就沒有了
13. The top and bottom layout guides表示對當前VC上下可見區(qū)域的邊際,如果不想視圖內(nèi)容穿過透明的bar延展,則各個控件單獨設(shè)置。
14. margins默認指定了視圖和子視圖的間隔,默認是8.
15. 蘋果建議:最好創(chuàng)建和它最鄰近的視圖的約束,避免直接設(shè)置view的寬高用最小或最大替代寬高,控件最好都有名字以方便定位,優(yōu)先使用前后而不是左右,代碼創(chuàng)建view時記得先設(shè)置translatesAutoresizingMaskIntoConstraints = NO,不然系統(tǒng)自動生成的約束可能與自己的約束相沖突. OSX和iOS中的Autolayout計算不一樣,OSX可以修改窗口的內(nèi)容和窗口大小,iOS只能修改當前場景的內(nèi)容。
16. 模糊的Autolayout造成的原因:缺少必要的約束來唯一限定位置和大小,可選約束優(yōu)先級是一樣系統(tǒng)不知優(yōu)先使用哪個。
17. 模糊的約束無法設(shè)置斷點調(diào)試也沒輸出,很難在運行時發(fā)現(xiàn),所以只用在調(diào)試中有方法可以檢測,對可能有問題的view在調(diào)試窗口 調(diào)用hasAmbiguousLayout,會返回布爾值?;蛘?_autolayoutTrace 來輸出診斷信息。
18. baseline alignment works only when the view is displayed at its intrinsic content height. If you stretch or shrink the view vertically, the text mysteriously appears in the wrong location.
19. If a control should always match its intrinsic content size, give it a very high content-hugging and compression-resistance priority (for example, 999).

AutoLayout官方參考

UIStackView是Autolayout的高級用法,幫你簡化各種約束。屬性distribution大概相當于是大小,alignment是排列,space是間距。核心便是方便垂直或水平排布多個subview,拖一個之后在其中添加子視圖都會自動按照你給stackview設(shè)置好的效果進行排布。它的removeArrangedSubview(_:)只是告訴Stack View不再需要管理subview的約束。而subview會一直保持在視圖層級結(jié)構(gòu)中直到調(diào)用removeFromSuperview把它移除。也可在stackview約束不夠時給子視圖添加約束。UIStackViewDistributionEqualSpacing, UIStackViewDistributionEqualCentering是用于stackview高度確定,subview的高度也確定,想讓subview比較均勻地分布在stckview中。均勻分布的方法不同,所以有2個選項。UIStackViewDistributionFillProportionally根據(jù)intrinsicSize自動按比例排列,UIStackViewDistributionFillEqually是指子視圖高度或?qū)挾榷家粯樱琔IStackViewDistributionFill就是填充,stackView要固定高,且約定除最后一個子視圖的各個其它子視圖的高度約束使最后一個不用設(shè)置高度約束就能剛剛好填充整個,如果沒有設(shè)置stackView的高度,則給定所有子視圖的高度,讓其自動計算stackView的整體高度。設(shè)置stack view的抗拉伸卡壓縮優(yōu)先級是沒用的因為stack view沒有intrinsicContentSize。如果修改stack view內(nèi)部元素和stack view外部元素的位置關(guān)系,要么捕獲約束代碼修改要么修改其抗拉伸或抗壓縮的優(yōu)先級。

ContentHuggingPriority 阻止控件被拉伸變大 ContentCompressionResistancePriority阻止控件被壓縮變小。注意:IB中當前的IntrinsicWidth都是基于你當前xib支持intrinsic內(nèi)容計算出來的尺寸。

// Compression Resistance
View.height >= 0.0 * NotAnAttribute + IntrinsicHeight
View.width >= 0.0 * NotAnAttribute + IntrinsicWidth
// Content Hugging
View.height <= 0.0 * NotAnAttribute + IntrinsicHeight
View.width <= 0.0 * NotAnAttribute + IntrinsicWidth
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,644評論 4 61
  • 目錄 0、前言 一、Auto Layout前世今生 二、Auto Layout基礎(chǔ)知識 1.Auto Layout...
    浮游lb閱讀 25,469評論 3 90
  • 轉(zhuǎn)載:http://www.cocoachina.com/swift/20161201/18198.html 前言...
    F麥子閱讀 4,511評論 2 8
  • 我們總是羨慕著電視劇里的情節(jié),主角總能有個光明的未來,總是能大展光芒,遺憾著自己無錢無勢無能無外表。但我們要明白人...
    唔安閱讀 378評論 0 0
  • Example: To work, ARC imposes some new rules that are no...
    anyoptional閱讀 273評論 0 2

友情鏈接更多精彩內(nèi)容