在iOS開發中,使用可視化編程能夠簡單快速的拖拽出令人滿意的UI。但是,除了簡單的拖拽之外,還有一項工作對于可視化編程來講必不可少,那就是AutoLayout自適應布局。因為,沒有進行AutoLayout的UI將無法適應屏幕大小不同的機型。本文主要基于Xcode 7.2.1總結一下個人在可視化編程中進行AutoLayout的幾點經驗,大神請繞過。
一、關于約束
在可視化編程中進行AutoLayout的方法就是添加約束。通過添加合適的約束,使控件能夠按照預期的位置和大小顯示在屏幕大小不同的機型上,也就實現了AutoLayout自適應布局。
1、添加約束
學習過可視化編程的小猿們應該都知道添加約束的幾種主要方法:
方法一:使用 Interface Builder 界面右下角的 Stack 、Align 、Pin 、Resolve Auto Layout Issues 四個約束操作按鈕。
方法二:在 Interface Builder 界面上,按住 control 鍵,從控件開始拖動鼠標到參考控件上,松開鼠標就會彈出約束選擇窗口(如圖 1-1)。
方法三:在 Interface Builder 界面左側的 Document Outline 窗口中,按住 control 鍵,從控件開始拖動鼠標到參考控件上,松開鼠標就會彈出約束選擇窗口(如圖 1-2)。
2、約束分類
從上面的截圖中我們可以發現,約束大致上可以分為三類:
2.1 ?距離約束
距離約束主要用于限定控件相對于參考控件的距離關系。相對于不同的參考控件,距離約束的具體名稱會有一些區別,但作用效果基本相同。例如:
相對于根 View 的距離約束為:Leading Space to Container Margin 、Trailing Space to Container Margin 、Vertical Spacing to Top Layout Guide 、Vertical Spacing to Bottom Layout Guide 。
相對于非根 View 的父 View 的距離約束為:Top Space to Container 、Leading Space to Container 、Bottom Space to Container 、Trailing Space to Container 。
相對于無包含關系的其它控件的距離約束為:Horizontal Spacing 、Vertical Spacing 。
2.2 ?對齊約束
對齊約束主要用于限定控件相對于參考控件的距離關系。同樣,相對于不同的參考控件,對齊約束的具體名稱也會有一些區別。例如:
相對于跟 View 或父 View 的對齊約束為:Center Horizontally in Container 、Center Vertically in Container 。
相對于無包含關系的其它控件的對齊約束為:Center Horizontally 、Center Vertically 。
2.3 ?寬高約束
寬高約束主要用于限定控件相對于參考控件的寬高關系,包括:Equal Widths 、Equal Heights 、Aspect Ratio 。
二、窺探精髓
上面講述了關于約束的基本內容,但具有可視化編程經驗的小猿們都清楚,只知道這些基本內容還遠不足以添加出能夠滿足各種 AutoLayout 需求的約束。所以說,接下來我們就深入其中,窺探精髓。
在 Interface Builder 界面中選中某個控件,我們就可以在 右側 Utilities 窗口 —> Size 選項卡 —> Constraints 選項 下查看已經添加的約束(如圖 2-1),并可以點擊 Edit 或者雙擊進入約束詳情對這些約束進行編輯。
或者我們可以直接在 Interface Builder 界面選中控件上的具體約束,在 右側 Utilities 窗口 —> Size 選項卡 下就會顯示約束詳情(如圖 2-2),可直接進行編輯。
約束詳情中都包括哪些內容呢?下面我們就來詳細了解一下。
在圖 2-2 中我們可以看到,約束詳情的最上面是約束的名稱,也就是圖中的 Center X Alignment Constraint ;最下面是一個 Placeholder 選項,內容是 Remove at build time ,從字面意思就可以知道,如果選擇了這個選項,編譯時將會移除這個約束,所以說一般情況下我們是不會勾選這個選項的;詳情中剩余的內容也就是需要重點講述的內容,其實這些內容都可以用 NSLayoutConstraint 的屬性進行描述:
First Item:(id firstItem 屬性).(NSLayoutAttribute firstAttribute 屬性),其中的 firstAttribute 屬性是可選的。
Relation:NSLayoutRelation relation 屬性,有三個選項可供選擇:Less Than or Equal(<=)、Equal(=)以及 Greater Than or Equal(>=),默認是 Equal(=)。
Second Item:(id secondItem 屬性).(NSLayoutAttribute secondAttribute 屬性),其中的 secondAttribute 屬性是可選的。
Constant:CGFloat constant 屬性,常數,可以手動輸入,用以對約束進行調整。
Priority:UILayoutPriority priority 屬性,優先級,默認值為1000,可以手動輸入,一般不做修改。
Multiplier:CGFloat multiplier 屬性,系數,可以手動輸入,用以對約束進行調整。
Identifier:NSString *identifier 屬性,約束標識。
這些內容遵循一個公式來限定約束:
First Item =(<=、>=) Multiplier × Second Item + Constant
這個公式就是約束的精髓,也就是可視化編程 AutoLayout 的精髓。公式中 First Item 的 firstAttribute 屬性和 Second Item 的 secondAttribute 屬性是可選的,Multiplier 系數和 Constant 常數可以手動輸入,所以說我們可以通過編輯約束來隨心所欲的修改約束,進而限定控件的位置和大小,實現可視化編程中的各種 AutoLayout 需求。
三、特殊需求
1、Label 的高度自適應
Label 的高度自適應非常簡單。具有可視化編程經驗的小猿們都知道,給 Label 加約束時不添加寬高約束也不會報錯,因為系統默認 Label 的 numberOfLines = 1,height = 20.5,寬度根據文字長短自適應。但有些時候,我們需要使用 Label 顯示一段很長的文本,就需要進行高度自適應:添加約束限定 Label 寬度,在 右側 Utilities 窗口 —> Attributes 選項卡 —> Label 選項 下將 Lines 設置為0。
2、ScrollView 的 AutoLayout
曾經嘗試過在可視化編程中對 ScrollView 進行 AutoLayout 的小猿們都知道,如果我們以 ScrollView 作為參考控件給其上的控件添加寬高約束,系統就會報錯。怎么辦呢?曾經有朋友告訴過我一個使用三方解決的方法,具體是什么三方我不記得了,因為我基本不會用這種方法。
那么我是怎么解決的呢?其實只要清楚問題的根源,我們就可以很簡單的解決它。
我們使用代碼創建 ScrollView 的時候,都必須要給定它的 contentSize 屬性,但是我們在可視化編程時并沒有對這一屬性進行設置。所以,當我們以 ScrollView 作為參考控件給其上的控件添加寬高約束時,系統自然就會報錯。解決問題辦法也就是在給 ScrollView 上的控件添加寬高約束時以除 ScrollView 以外的其它控件作為參考控件。
考慮到我們可能會在 ScrollView 上添加很多個控件,最好的作法就是先在 ScrollView 上添加一個空白 View 作為 contentView ,添加好約束后將需要添加的控件添加到 contentView 上,這時就可以按照正常添加約束的方法給這些控件添加約束了。下面的動畫演示的是在 ScrollView 上添加一個與根 View 等寬、高度為根 View 高度2倍的 contentView ,并添加約束的過程:
3、TableViewCell 的高度自適應
在實際開發中可能經常會遇到 Cell 的高度要根據顯示的文字的多少進行調整的需求,這種情況下,如果我們通過可視化編程來定制 customCell ,又該怎樣添加約束來使 customCell 的高度能夠自適應呢?
首先,我們要給 customCell 中顯示文字的 Label 添加約束:
第一步:限定 Label 的寬度,但不要限定 Label 的高度,因為 Label 高度自適應之后 customCell 才能高度自適應;
第二步:通過 Leading Space 或 Trailing Space 或 Center.X 限定 Label 在水平方向上的位置;
第三步:限定 Label 的 Top Space 和 Bottom Space 兩個距離約束;
第四步:在 右側 Utilities 窗口 —> Attributes 選項卡 —> Label 選項 下將 Lines 設置為0。
然后,我們要在代碼中設置 TableView 的 estimatedRowHeight 和 rowHeight 屬性:
self.tableView.estimatedRowHeight = 30 ; ? ? // 設置 customCell 的估計高度
self.tableView.rowHeight = UITableViewAutomaticDimension; ? ? // 設置 customCell 自適應高度
這樣,我們就實現了 TableViewCell 的高度自適應。
四、實例演示
接下來根據實際開發中的一個 AutoLayout 需求,來給大家做一個小小的演示。之前一個朋友給提了一個 AutoLayout 的需求,具體的 UI 效果如圖 4-1,要求三個 ImageView 等寬等高,之間的兩個間隔和屏幕邊緣的兩個間隔寬度相等。朋友告訴我說他是在四個間隔區域使用了四個空白的占位 View ,然后再添加如下約束:
1、添加距離約束:限定兩邊的空白 View 與屏幕邊緣的距離為0,限定四個占位 View 與三個 ImageView 兩兩之間的距離為0;
2、添加對齊約束:限定四個占位 View 和三個 ImageView 相對于根 View 豎直居中;
3、添加寬高約束:限定四個占位 View 和三個 ImageView 的高度均為 0.2 × 屏幕高度,限定四個占位 View 的寬度均為 0.07 × 屏幕寬度,限定三個 ImageView 的寬度均為 0.24 × 屏幕寬度。
如果試著把這些約束添加一遍,就會發現這種方法非常麻煩,還容易出錯。但是,這篇文章讀到這里,我們已經完全沒必要再使用這種浪費空白占位 View 又非常麻煩的方法了。我們完全可以只對三個 ImageView 添加約束來實現圖 4-1中的 UI 效果。計算 Multiplier 系數的過程請自行腦補,下面只演示添加約束的過程:
Notes:
1、衷于分享,歡迎轉載;
2、博主才疏學淺,敬請批評指正;
3、如果對您有所幫助,我倍感榮幸,也請您點個贊。