autolayout 從精通到忘記

1、autolayout的計算公式:

firstItem.firstAttribute(R)SecondItem.secondAttribute*m+b;R:relations:Multiplierb:Constant


autolayout從這里開始

2、優先級

Hugging priority 確定view有多大的優先級阻止自己變大。
Compression Resistance priority確定有多大的優先級阻止自己變小。
tip1:
content Hugging就是要維持當前view在它的optimal size(intrinsic content size),可以想象成給view添加了一個額外的width constraint,此constraint試圖保持view的size不讓其變大:
view.width <= optimal sizecontent Hugging默認為250.
tip2:
Content Compression Resistance就是要維持當前view在他的optimal size(intrinsic content size),可以想象成給view添加了一個額外的width constraint,此constraint試圖保持view的size不讓其變小:
view.width >= optimal sizeContent Compression Resistance默認優先級為750.

52111B78-BDAE-47FF-8C97-323F3D03F378.png

3、AutoLayout 與 UIScrollView的相遇

a、首先給scrollview加上高和上左右的約束

A4261C50-85F8-4D3A-988D-FAF907DB2B53.png

b、再給image加上高和上左右的約束,放在scrollview中

346A475C-298F-4B1A-A08F-2B4982776725.png

但是有問題?
問題的原因:
我們知道UIScrollView最重要的就是其contentSize的寬高了,如果這個無法確定,那scrollview就無法知曉可以滾動查看的區域。其實這僅僅是表象,IB不會因為contentSize的可見區域不確定而抱怨,因為它會有一個默認的可見區域就是其bounds,其實IB真正抱怨的是其內部的subViews的布局對于它的依賴,比如我們看image相對于上、左、右的約束都相對于scrollview的。scrollview內部的subViews的約束全依賴于scrollview,這樣子的話,問題就來了,Scrollview和image一樣都會根據內容調整其contentSize(autolayout布局模式中,image這種控件都會根據內容對自身寬高進行調整),如果Scrollview要根據其subviews來調整自身的contentsize,而其subviews又要根據scrollview的contentsize調整自身的布局,是不是就矛盾了,就成了相互依賴了。
所以IB要求UIScrollview(當然包括繼承于它的UITableview、UIWebview這些控件)的contentSize必須在布局時能夠確定。
解決方法:
1、創建一個空白的UIViewController
2、將UIScrollView添加到UIView控件中,并設置UIScrollView針對父視圖UIView的constraints(Leading/trailling/top/bottom = 0 || Leading/trailling/top= 0 + height=X )
3、最主要的來了,添加UIView控件到UIScrollView中。。
(1)并改名為ContentView....(UIScrollView主要是靠子視圖來實現autolayout的高度和寬度的計算)
(2)然后設置ContentView的針對父視圖UIScrollView的 constraints
1、Leading/trailling/top= 0
2、bottom = 1
3、equal height / equal width (ContentView的高度和寬度 與 UIScrollView相等)
4、設置equal height的優先級 priority 小于 剛才設置的bottom的優先級(該bottom的是ContentView針對UIScrollView的constraints),這里設置priority=999.

4FDF30CE-0318-4E1B-834F-92A80DE88CAB.png

這里需要注意
第一:為什么 bottom =1 而不是 bottom = 0。在實際開發中,如果為0,并且ContentView中的內容高度不超過屏幕的高度時,uiscrollview不能下上拉動。
第二:要實現ContentView 的高度自適應為uiscrollview的contentSize的高度,需要ContentView中的子視圖有明確的top與bottom,用來讓autolayout計算出ContentView的實際高度.
第三:為什么要設置equal height 的優先級。。。我們來寫個公式更容易理解
因為scrollview.height = uiview.height
又因為ContentView.height = scrollview.height - 1
所以ContentView.height != scrollView.height
也就是不能實現equal height 這個constraints。。會報錯。
只要調整一下優先級就可以解決這個問題,出現沖突,優先適應ContentView的高度....現在你可以在ContentView上添加你想添加的控件,但記住如果你要添加的控件已經超出了屏幕的高度,你需要給ContentView里面的子控件加上bottom 和 top(不超過你也可以添加),這樣autolayout才能計算出ContentView的高度,并將這個高度賦給UIScrollView的ContentSize,實現自適應高度。還需要注意一點就是如果最下面的控件已經超出界面外了,那么在添加bottom to ContentView的這個約束時,XCode默認是-xxx的,這個時候如果在模擬器上運行的話,可以看到還是滑動不到最下面去。所以要把這個約束值改為0或者大于0.
tip
如果代碼中設置了self.automaticallyAdjustsScrollViewInsets = NO;,那么則需要把ContentView中的最下面的控件的bottom to ContentView 約束+44.導航欄的高度。ContentView中如果使用UILabel,要給uilabel明確的height constraint,這樣auto layout才能計算出高度。

4、遇到過的小挫折

需求描述
首先這個頁面已經布好局噠。有一個scrollview,scrollview里面有一個contentview,都已經布局好噠。
然后要往里面增加一個bannner,這個banner距lastlabel為20,距superview的bottom是10。
最后這個banner表示不是常駐居民,要求出現時如果屏幕顯示不全求滾動,不出現時如果屏幕顯示完全不滾動。
解決思路描述
鄙人思路一:直接把banner丟ContentView里面。
鄙人否決一:由于頁面的ContentView是與屏幕等heigh的,所以當加入banner后ContentView里面的子控件的高度和大于屏幕的高度就報錯。

16B5EFF9-F9D9-4497-87DC-B324A7D8B0EE.png

鄙人思路二:根據思路一直接把banner的height設為0,IB就不會報錯啦,再在運行時把banner的height設為X。
鄙人否決二:于是乎,如圖所示,ContentView為了不讓它所以子控件的高度和超過自己的預定高度,ContentView把banner壓扁了。。。。

D57571D4-4F09-411A-B63B-A6B8C26FDC4F.png

在經過幾番思想的掙扎之后,終于尋找到了解決之道,GOOD!
鄙人思路:直接把banner丟scrollview里面,讓banner與ContentView并排。
鄙人解析:scrollview.contentView.height = contentView.height + bannner.height。所以只要contentView.height與bannner.height是實值IB就不會有問題啦。

1480670130072.png

此處有演示小demo
https://github.com/HFavour/ShowTest.git
demo中有兩個小拓展。

1480909021745.png

俗話說,正在精通的技術已經融化在思維中。。
所以。。。
后來。。。。我仿佛只記住了那一個公式。。。

最后,附上本文的參考鏈接:
http://www.lxweimin.com/p/f3c0f040c07a
http://www.lxweimin.com/p/25ddadddae06
http://www.lxweimin.com/p/248c5ed719ec

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容