1. 程式人生 > >iOS 10 Auto Layout介面自動佈局系列1-自動佈局的基本原理

iOS 10 Auto Layout介面自動佈局系列1-自動佈局的基本原理

蘋果今年如約放出了新的iPhone 7與iOS 10系統,SDK針對新的裝置和系統的介面適配也進行了若干改進,因此我也想借此機會跟大家分享一下我自己關於介面自動佈局的理解,如有錯誤請不吝指教。

一、檢視定位的基本原理

檢視(View)是一個用於顯示內容的矩形區域,它是構成app介面的最基本單元。下圖為計算器app的橫屏介面,其中每一個計算器按鍵都是一個檢視。


在平面直角座標系中,要準確描述一個矩形需要確定以下四個佈局屬性(Layout Attribute),即水平位置x垂直位置y寬度w高度h(暫不考慮旋轉)。只有上述4個佈局屬性都明確的情況下,該檢視才能正確新增到介面中。

以上圖為例,如果要將數字鍵5新增到介面中,則程式碼類似為:

UIView* number5View = [[UIView alloc] initWithFrame:CGRectMake(x, y, w, h)];
[parentView addSubview:number5View];

上述程式碼詳細給出了該檢視的4個佈局屬性的值,我們姑且稱這種方式為“顯式座標定位方式”

二、舊的介面佈局方式及其缺點

請思考以下問題:

  • 顯式座標定位方式在處理檢視數量很多時會遇到什麼問題?
  • 顯式座標定位方式在處理橫豎屏旋轉時會遇到什麼問題?

首先,當檢視數量很多的情況下,由於每個檢視都需要明確給出4個屬性,因此構建每一個檢視非常繁瑣而又容易出錯。而且,當發生介面變化(例如橫豎屏旋轉)時,你需要重新計算每個檢視的新的佈局屬性值。這顯然不是一個令人滿意的解決方法。

於是蘋果給出了一個更好的解決方法,就是在建立檢視的同時給出其相對於父檢視的“對齊方式與縮放係數”,即autoresizingMask。當父檢視發生變化時,通過每個子檢視的autoresizingMask即可自動得出新的位置,而無需開發者提供。例如上圖中的等號鍵,即可以指定其對齊方式為右對齊、下對齊,指定其縮放係數為固定寬度、固定高度。這樣就保證了等號鍵總位於其父檢視的右下角且寬高不變。

蘋果解決問題的出發點是好的,通過給出介面變化的規則來自動計算出佈局屬性的值,從而省去開發者的工作。

然而autoresizingMask的問題在於:

  • 其描述介面變化規則不夠靈活,很多變化規則根本無法精確描述。autoresizingMask縮放比例是UIKit內部計算的,開發者無法指定縮放比例的精確值。
  • 變化規則只能基於父檢視與子檢視之間,無法建立同級檢視或者跨級檢視之間的關係。例如,對於上圖的計算器,autoresizingMask無法描述數字鍵5緊貼在數字鍵8下面,以及數字鍵0左側與數字鍵1左側對齊且數字鍵0右側與數字鍵2右側對齊這樣的規則。

因此在過去,很多時候開發者還不得不硬著頭皮使用顯式座標定位方式來解決轉屏(例如重寫layoutSubviews方法),或者分別做橫屏與豎屏兩套介面。

這些開發者都能忍,然而噩夢才剛剛開始。。。

iPhone 4s及早期iPhone螢幕的尺寸是固定的(3.5寸屏:320*480),基本上在測試機上執行的效果就是使用者執行的效果。但此後的新版iPhone為16:9的寬屏,解析度也各不相同(4寸屏:320*568,4.7寸屏:375*667,5.5寸屏:414*736),另外有的app還需要同時支援iPad。難道所有這些裝置都需要開發者去自己處理每個檢視的精確位置,自己去處理轉屏嗎?

蘋果也意識到了這樣的問題,因此在iOS 6釋出的時候引入了自動佈局(Auto Layout)佈局約束(Layout Constraint)的概念,來解決上面遇到的問題。

三、自動佈局的原理與使用方法

自動佈局是對autoresizingMask的進一步改進,它允許開發者在介面上的任意兩個檢視之間建立精確的線性變化規則。所謂線性變化就是數學中的一次函式,即:

y = m*x + c

其中x和y是介面中任意兩個檢視的某個佈局屬性,m為比例係數,c為常量。例如,如果我們想描述數字鍵5緊貼在數字鍵8下方,我們可以建立如下規則:

  • 數字鍵5的水平中心x座標 = 1.0 * 數字鍵8的水平中心x座標 + 0.0  //8和5水平中心對齊
  • 數字鍵5的頂部y座標 = 1.0 * 數字鍵8的底部y座標 + 0.0  //8的底部為5的頂部
  • 數字鍵5的寬度w = 1.0 * 數字鍵8的寬度w + 0.0  //8和5寬度相等
  • 數字鍵5的高度h = 1.0 * 數字鍵8的高度h + 0.0  //8和5高度相等

每個線性變化規則稱之為佈局約束(Layout Constraint)。由於每個檢視需要確定4個佈局屬性才能準確定位,因此一般來說都需要建立4個佈局約束。

在下一篇文章中,我將詳細介紹新增自動佈局約束的方法,敬請關注。