iOS autoLayout總結

本文轉自 http://ruikq.github.io/ios/autolayout/uiscrollview/2015/01/27/iOS-autolayout%E6%80%BB%E7%BB%93.html

 autolayout, and uiscrollview

之前學習iOS的時候沒怎麼接觸過autoLayout,自從iPhone6個6+出來以後一直在爲之前的app作適配,因此使用了大量的autoLayout作適配,一開始很不習慣,可是越用越以爲好用,接觸到如今遇到不少問題,在這裏總結一下,包括三部分:限制的優先級、autoLayout下得UIScrollView和UITableView。html

優先級

在一開始autoLayout的使用過程當中,優先級經常是被我所忽略掉的,因此有的時候在一些稍微複雜的佈局中每每會出現一些很奇怪的問題和警告,尤爲是佈局一些大小隨內容改變的控件時(UIButton、UILabel、UIImageView),而這些問題和警告均可以經過優先級來解決,下面以UILabel爲例子來總結一下:ios

圖1

以上是UILabel的限制,都是採用默認的優先級,當點擊長文字按鈕的時候label上附有長文本,點擊短文字按鈕則是短的文本。git

首先看一下Content Hugging Priority如下部分,一開始使用autolayout的時候我是沒有關注到這一部分的。Content Hugging Priority的的意思是限制內容變大優先級,下面對應橫向和縱向,Content Compression Resistance Priority是限制內容縮小優先級,最下面的Intrinsic Size則是設置內容固定大小。github

爲更好理解上述術語的意思,demo中只關注了橫向。運行demo不管點擊長文字仍是短文字按鈕label的大小都是不會改變的。下面經過改變一些優先級來使label大小隨文字大小改變,首先將label的Trailing的限制優先級改成700,其餘不變,而後運行,發現label可隨文字變大但不能變小,這是由於label的右邊距離父視圖的優先級700小於750,因此Trailing Constrain失效,限制內容變小的限制生效,因此當label內容變多時就限制住label變小,可是Content Hugging Priority的優先級爲251小於700,當文字少時沒法阻止label變大,如今改變Content Hugging Priority爲800。objective-c

圖2

出現警告,指望label寬度0,是由於在storyboard設計階段自動計算label文字寬度爲0,因此label大小也爲0;能夠經過設置Intrinsic Size 爲PlaceHolder去掉警告,這裏告訴storyboard設置一個臨時佔位尺寸,這個佔位尺寸僅在storyboard設計階段有效,不會影響到運行時的尺寸,運行,如今正常了。app

圖3

UIScrollView

autoLayout下,UIScrollView的contentSize是由其中的內容大小來決定的,依賴關係和正常的子視圖依賴父視圖是相反的,因此UIScrollView的子視圖的佈局約束是不能夠經過UIScrollView來肯定的,因此通常狀況下的約束到了UIScrollView中就會出現不少錯誤和警告。佈局

要處理這種狀況就去要肯定UIScrollView中子視圖的寬和高,可是這又和autoLayout下寬、高的可變性衝突,目前的方法是引進一個錨點視圖,子視圖的寬和高根據錨點視圖肯定。post

圖4

anchorViewForWidth是一個寬和父視圖相等,高爲0的視圖,contentView的高固定、寬度和anchorViewForWidth相等,咱們也必須設置contentView的top、trailing、leading、button,這不影響contentView的大小,這至關因而UIScrollView可滾動區域的旁白,因此像這樣在通常視圖中看上去重複設定限制會發生警告,但在這裏就不會出現。學習

在縱向滑動的UIScrollView項目中contentView的寬度依賴能夠這麼設置,上面的contentView的高度咱們是固定的,但若是高度是隨運行時肯定的咱們就不能夠設置固定了,在ios8中像UILabel、UIButton、UIImageView這類大小隨內容改變的控件咱們是不須要設定高度,系統會自動根據內容計算,若是控件中的內容是動態得到的,咱們能夠設定placeHolder佔位尺寸來進行預設定;ui

圖5

設置placeHolder以後

圖6

而對於系統沒法計算的控件雖然設置了placeHolder沒有了警告,可是運行時控件卻不可見,因此只有先設定高度固定再將限制映射爲變量,運行時計算修改constant。

圖7

UIScrollView中的注意事項

一、有些狀況下UIScrollView不能滾動 緣由是使用autoLayout以後,在ViewDidLoad以後,系統會從新計算控件的一些值會致使UIScrollView的ContentSize變爲(0,0),因此須要在viewDidLayoutSubViews方法中從新設置UIScrollView的contentSize,但有時在ios7上不行,ios7須要在viewDidAppear:animated方法設置contentSize。

UITableView

在UITableView的cell中使用autoLayout,能夠根據內容自己來計算cell的高度,在iOS8中只要將tableView.rowHeight設置爲UITableViewAutomaticDimension,系統就會根據cell設定好的約束自動計算出高度,在iOS7中須要使用systemLayoutSizeFittingSize:方法來根據約束計算cell的Size,而在iOS6中咱們須要手動計算cell的高度。

UITableView使用autoLayout比UIScrollView要簡單,惟一讓我遇到麻煩的是tableHeaderView,在xib文件中加入tableHeaderView以後是沒法改變他的位置的,也不可以使用autoLayout增長約束,這就沒法動態的改變tableHeaderView的高度;在搜尋了StackOverflow以後發現不須要對tableHeaderView設置autoLayout,想要改變tableHeaderView的高度直接更改frame就能夠了。

CGRect headerFrame = self.listView.tableHeaderView.frame; headerFrame.size.height = 47; self.listView.tableHeaderView.frame = headerFrame; [self.listView setTableHeaderView:headerView]; self.listView.contentOffset = CGPointZero;

對於將外部自定義的view做爲tableHeaderView,不能將frame大小設置在自定義的view中,必須也要和上面同樣從新設置frame,不然會出現tableHeaderView遮擋cell、tableHeaderView拉伸和顯示不全等奇怪現象。

總結

autoLayout是ios6就提出來的東西,一開始由於體驗差、操做煩用的人不多,可是之後的開發中它是必不可少的,由此我想到了Swift,雖然如今剛剛出現版本還不成熟,可是之後一定是慢慢替代Object_C的,由於蘋果不會出一個雞肋東西。接觸autoLayout以來已經有好幾個月了,也是適配不少UI,autoLayout是一個越用越順手的東西,若是出現奇怪的問題就說明某個點尚未掌握,須要再去細細學習。最後附上demo代碼

相關文章
相關標籤/搜索