使用 UIStackView 來簡化 AutoLayout 布局

可以維護的 AutoLayout

在使用 AutoLayout 做界面布局的時候,你會發現,做好一個復雜界面的約束并不是一件容易的事,經常需要很多的調試,這在用代碼寫布局的時候尤為明顯,因為沒有 IB 給你實時的反饋當前的 Layout 錯誤。而且不管是在 IB 還是純代碼的 AutoLayout,其可讀性都不太好,例如我們創建了下面這樣一個 App Store 的界面:

1.png

Label 和 星標圖片之間有很多約束,如果我們遇到了需求改動,想要在星標上方多加一行,就得先搞清楚各個約束是干什么的,再打破幾個約束,最后增加一個 Label 并且加上約束,費時費力。

iOS 9 發布的時候蘋果提供了一個新的AutoLayout 工具 UIStackView,可以自動完成很多類型的布局,并且不用添加任何約束,由 UIStackView 自行管理其 ArrangedSubviews 的約束并且可以讓增刪變的更簡單,大大增加了項目的可維護性,本文就來介紹一下 UIStackView 的使用。

UIStackView 本身是建立在 AutoLayout 的約束之上的,我們不用主動給其子視圖添加約束就可以完成自動布局,UIStackView 相當于一個可以為你自動管理內部 View 的一個容器。想要完成布局大多數情況你需要做這三步:

1.調用 -addArrangedSubview: 添加需要布局的 View 到一個 UIStackView 上;
2.配置 UIStackView 的 axix、alignment、distribution、spaciing 這四個屬性;
3.如果有必要,再嵌套多個 UIStackView 到一個 UIStackView 中。

UIStackView 的主要方法和屬性

2.png
@property(nonatomic) UILayoutConstraintAxis axis;

用于控制 UIStackView 子視圖橫向或縱向布局,有兩種:

  • UILayoutConstraintAxisHorizontal 橫向布局
  • UILayoutConstraintAxisVertical 縱向布局
3.png
@property(nonatomic) UIStackViewAlignment alignment;

這個屬性稍微復雜一點,當 axisHorizontal 時其表示 UIStackView 的子視圖相對于其上下邊界的對其方式。當 axis 為 Vertical 時,表示 UIStackView 的子視圖相對于其左右邊界的對其方式,一共有八中,看下面的圖示就很好理解了:

4.png
5.png
@property(nonatomic) UIStackViewDistribution distribution;

這個屬性用來控制 UIStackView 在其 axis 方向上的分布,分別有如下幾種:

6.png

Fill
UIStackView 的子視圖會沿著其 axis 填充滿 UIStackView,如果子視圖在 axis 方向上不能放入 StackViewStackView太小),則會按照子視圖的抗壓縮優先級屬性( Content Compression Resistance Priority)從低到高壓縮視圖,直到正好填滿 StackView 為止。

反之,如果子視圖在 axis 方向不能填滿 StackViewStackView太大),則會按照子視圖的抗拉伸優先級屬性(Content Hugging Priority)從低到高拉伸視圖,知道正好填滿 StackView 為止。

這里說一點,StackView 在沒有寬高約束的時候大部分情況是沒問題的,因為它會根據子視圖的intrinsic content size 、寬高約束、甚至是 frame.size.width frame.size.height 來計算自己的寬高,最終會有一個intrinsic content size,這樣我們把 StackView 添加到父視圖中的時候,可以不約束其寬高,只定位好 origin 就可以了。

FillEqually
這個屬性簡單一些,StackView 的子視圖會沿著axisStackView 內均勻分布。

FillProportionally
按字面意思解釋,和 FillEqually 類似,也是每個子視圖都會被等比例拉伸或者壓縮,來填滿 StackView,但是這個是等比例填滿,每個子視圖會被 StackView 按照其 intrinsic content size 或者其本身 frame 來進行等比例縮放,如果要拉伸或者壓縮,每個子視圖都會同時被等比例拉伸或壓縮。

EqualSpacing
StackView 會在每個子視圖中間留下等相等的空間距,此時 Spacing 屬性定義的是這個間距的最小值。如果 StackView 足夠大,可以保持子視圖的原始尺寸,不拉伸,但是如果 StackView 太小,子視圖會被壓縮,也是按照子視圖的抗壓縮優先級屬性( Content Compression Resistance Priority)從低到高壓縮,此時如果有兩個子視圖有相等的抗壓縮優先級,StackView 就不知道壓縮哪個了,需要調整子視圖的優先級,不要出現相等的情況。

EqualCentering
StackView 會把每個子視圖按照中心點等距離排列,此時 Spacing 屬性定義的是這個間距的最小值。如果 StackView 足夠大,可以保持子視圖的原始尺寸,不拉伸,但是如果 StackView 太小,子視圖會被壓縮,也是按照子視圖的抗壓縮優先級屬性( Content Compression Resistance Priority)從低到高壓縮,此時如果有兩個子視圖有相等的抗壓縮優先級,StackView 就不知道壓縮哪個了,需要調整子視圖的優先級,不要出現相等的情況。

@property(nonatomic) UIStackViewAlignment alignment;

按照 distribution 屬性中的布局方式控制子視圖之間的間距。

總結

在本文結束之前,我們看一下上面的 AppStore Demo 在使用 UIStackView 布局后的情況,是不是簡介清爽了許多。

7.png

最后,引用一下 WWDC 蘋果工程師的話,如果你使用 AutoLayout,那么請 Start With Stack View, use constraints as needed!

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

推薦閱讀更多精彩內容

  • 目錄 0、前言 一、Auto Layout前世今生 二、Auto Layout基礎知識 1.Auto Layout...
    浮游lb閱讀 24,860評論 3 89
  • 翻譯自“Auto Layout Guide”。 1 入門 1.1 理解自動布局 自動布局根據視圖層級結構中視圖上的...
    lakerszhy閱讀 3,678評論 3 26
  • 前言 首先,我們通過下面這張圖片引出今天的主角 大家看到了什么,是愛嗎?不,這不是愛,不是愛,是滿滿的‘愁緒’???...
    一念之見閱讀 2,223評論 0 2
  • 我的博客, 各位看官有時間賞光 UIStackView UIStackView介紹 隨著autolayout的推廣...
    VIC_LI閱讀 9,220評論 0 17
  • 初入社會,進入一家初創型互聯網公司,開始漫長的上班族生活。 開始的一個月,每天很閑,自己也相當享受悠閑的上班時光,...
    Masdu閱讀 250評論 0 0