iOS回顧筆記(06) -- AutoLayout從入門到精通



iOS回顧筆記(06) -- AutoLayout從入門到精通

隨着iOS設備屏幕尺寸的增多,當下無論是純代碼開發還是Xib/StoryBoard開發,自動布局已經是必備的開發技能了。

我使用自動布局也有一段時間了,遇到了不少問題,在解決的過程中也收獲了很多知識。尤其是在使用熟練之后開發速度上的提升非常明顯。這里把AutoLayout的基本使用和個人使用心得匯總一下,希望能幫助到大家!

適配的概念

適配主要分兩種

  • 系統適配

    系統適配主要指適配不同版本系統,如 iOS 6(擬物化) 到 iOS 7(扁平化)兩個系統系統的適配,我們需要寫不同的代碼來保證項目在不同系統上的美觀與可用。

  • 屏幕適配

    屏幕適配主要是針對不同尺寸的屏幕進行適配,同一個頁面再不同尺寸屏幕上的布局,如Safari在手機橫豎屏下的布局等等。

常見設備的分辨率:

Snip20170313_1.png

屏幕適配發展史

  • iPhone 4s 以前的時代

iPhone 4s 和之前設備的屏幕都是3.5英寸,可以說沒有屏幕適配,所有的坐標點就是 320*480.
適配完全使用frame、bounds、center進行計算,代碼基本寫死。

// 直接寫死
UIImageView *iv = [UIImageView new];
iv.frame = CGRectMake(50, 300, 200, 80);
[self.view addSubview:iv];
  • iPad、iPhone橫屏時代

    • 出現 AutoResizing 技術

      • 優點:

        • 解決了父子控件相對位置的問題
        • 子控件可根據父控件的行為發生相對應的變化
        • 讓橫豎屏的適配變得簡單
        • 無法處理兄弟控件相對位置的問題
      • 使用前提:

        • 關閉AutoLayout
      • 局限性:

        • 只能解決父子控件的相對關系,
        • 無法解決兄弟控件之間的相對關系

       

    • AutoResizing在Xib中的使用介紹

    在Xib中主要有6根線來設置AutoResizing

Snip20170313_2.png
外部四根線

外部四根線分別表示上、下、左、右四個方向,子控件相對於父控件的距離。
實線:表示固定位置
虛線:表示非固定位置

**內部兩根線**

內部兩根線分別表示水平和豎直方向,子控件是否根據父控件等比例縮放。
實線:該方向上跟隨父控件等比縮放
虛線:該方向上不跟隨父控件等比縮放


- **AutoResizing在代碼中的使用介紹**

通常代碼中子控件在添加到父控件之前設置AutoResizing對應的屬性值,其代碼屬性值和Xib中相反,代碼中設置可變部分,Xib中是選中部分為固定不變的。

    // 上下左右四個方向參數(與Xib中設置相反)
    UIViewAutoresizingNone                 = 0, 
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
    
    // 寬高是否根據父控件等比縮放
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
    

比如要設置一個UIView與其父控件關系為右下角對齊
示例代碼如下:

XYBannerView *banner = [XYBannerView bannerView];
banner.frame = CGRectMake(80, 20, 200, 90);
banner.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin;
[self.view addSubview:banner];
  • iOS 6之后

    • 出現了AutoLayout技術

    AutoLayout彌補了AutoResizing的局限性,不僅可以解決父子控件之間的相對關系,還可以描述兄弟控件之間的相對關系,還可以描述自身關系等,功能非常強大。

    AutoLayout的兩個核心概念

    • 參照
    • 約束

AutoLayout介紹和使用

Xib中常用的面板

Xib 主要有以下三個面板

  • Align : 對齊方式

Snip20170313_4.png

  • Add New Constraint: 添加新的約束

Snip20170313_5.png

  • Resolve Auto Layout Issues : 修復自動布局問題 Snip20170313_7.png

AutoLayout的使用原則

AutoLayout是為了確定View的frame(確定View的Point和Size)。

  • 至少添加四個約束,寬高和位置來確定frame
  • 避免約束沖突
    1.如同一個View的寬設置兩次,一個100,一個200,導致無法確定,形成沖突,沖突屬於錯誤,須解決: Snip20170314_1.png
    2.如約束不夠,無法確定View的frame時候也會報錯:

Snip20170314_3.png

  • AutoLayout的警告:警告一般是Xib中添加好了約束,但是對應View沒有移動到對應位置導致。這種情況程序運行起來之后會是正確約束的樣子,而不是Xib中的樣子。

    • 警告解決辦法:
      1.選中View,update frame 或使用快捷鍵‘command’ + ‘option’ + ‘=’
      2.如圖:Snip20170314_2.png
  • 約束的修改:
    約束的修改有很多種方式,下面列舉一種我常用的方式!
    Snip20170314_4.png

注意:上面說的Add New Constaints面板只能添加新的約束,修改不能在那里。

AutoLayout案例練習

AutoLayout這種靈活的實用技術最直接的學習辦法就是實戰練習,下面幾個小案例來展示一下。

練習1

1.在控制器底部添加兩個View,一個紅色,一個藍色
2.兩個View的高度、寬度永遠相等
3.距離父控件左邊、右邊、兩者中間和距底邊的距離相等
示意如圖:
Snip20170314_5.png

根據:添加四個約束確定frame,避免沖突和警告的原則。我們按照要求添加約束
1.兩者等高等寬:使用Add New Constraints面板
Snip20170314_6.png

或者可以直接拖線:選中紅色 按住‘control’鍵拖線到藍色
Snip20170314_8.png

2.設置紅色View約束
選中紅色View打開Add New Contraint面板設置對應約束
Snip20170314_9.png

3.設置藍色View約束
選中紅色View打開Add New Contraint面板設置對應約束,其中藍色View的約束同上圖,只需要設置藍色的右邊距同紅色相等 為 20 即可(其他約束在設置紅色的時候已經有了)

4.設置紅藍色View等高/底
設置等高/底 和上面設置兩者等高等寬步驟一致,選擇 Top/Bottom即可。

效果:
練習1.gif

 

練習2

同樣兩個View 一藍一紅
1.兩個View的高度相等
2.紅色View和藍色View的右邊對齊
3.藍色View距離父控件的左右相等,且距離紅色View的間距相等
4.紅色View的左邊和藍色View中點對齊
Snip20170314_10.png

1.設置藍色View約束
藍色View約束:距離父控件邊距和紅色View的邊距
Snip20170314_11.png

2.設置紅色View和藍色View等高 和邊距

1.設置兩者等高,直接拖線即可
2.設置紅色view的邊距直:距右 20 和 距底邊 20。(參考上圖)

3.設置紅色View與藍色View的中心對齊

紅色View和藍色View的中心對齊可轉化為 紅色View長度為藍色一半。可先設置等寬再修改等寬約束。
Snip20170314_14.png

效果圖:

練習2.gif

練習3

四個相同的View均分占據屏幕的四個角,如圖
Snip20170314_15.png

1.四個view是等寬等高
直接分別設置四個的等寬等高,拖線就很方便

2.四個view互相之間的間距為零
使用Add New Contraint面板分別添加每個View的四邊距 為0即可

最終效果如圖:
練習3.gif

AutoLayout 中的UILabel

UILabel相對比較特殊一點,需要單獨說一下。

在不使用 AutoLayout的時候 UILabel 內部的文字默認是居中顯示的,如果設置的Size較大,而內部文字較少就會造成上下留白,從而造成資源的浪費。

在實際的使過程中,需求往往是UILabel正好包裹住內部的文字。

有了AutoLayout之后的UILabel在添加約束的時候可以不用添加高度,系統會自動計算內部文字高度來自適應UILabel的高度!

Snip20170314_18.png

實際應用中經常需要設置UILabel的根據文字多少來自動適應高度,並且UILabel.width <= 某個值.
這種情況需要給UILabel添加寬度約束,比例關系設置為Less Than Or Equal
Snip20170314_19.png

練習4

1.設置兩個View,兩者間距為0,一紅一綠,
2.紅色View內部有一個UILabel,
3.根據Label內部的文字自適應高度,
4.點擊屏幕修改Labe內部文字,讓其父控件的frame也自動適應
Snip20170314_20.png

1.設置兩個View一紅一綠,分別設置邊距等約束
2.紅色View中添加UILabel,設置Label的文字和約束,設置Label高度自適應

最終效果圖:
練習4.gif

這只是幾個簡單的小練習,若想使用熟練AutoLayout還需要認真練習

AutoLayout在代碼中的使用

以上講了AutoLayout的可視化使用,但是項目中有很多頁面是動態生成的,需要我們用代碼實現,所以下面講講AutoLayout的代碼實現

代碼實現的特點:繁瑣、技術含量低

Xib中的每一條拖線對應代碼中一個 NSLayoutConstraint 對象,從NSLayoutConstraint頭文件中可以查看其對象的創建方法:


    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:view1 
    attribute:attr1 relatedBy:NSLayoutRelation toItem:view2 attribute:attr2 
    multiplier:multiplier constant:c];
    
    參數含義:
    
    view1:                  約束的第1個View
    attr1:                  第1個View的屬性
    NSLayoutRelation:       兩個View的屬性之間的關系
    view2:                  約束的第2個View
    attr2:                  第2個View的屬性
    multiplier:             倍數關系
    c:                      需要增加的常量
    

上面的方法可以整合成一個自動布局的核心計算公式

obj1.property = (obj2.property) * multiplier + c

代碼添加AutoLayout的步驟

  • 利用NSLayoutConstraint類創建具體的約束對象
  • 添加約束到對應的View上
- (void)addConstraint:(NSLayoutConstraint *)constraint; 
- (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints;

代碼添加AutoLayout的注意點

  • 需要先禁止AutoResizing功能,設置如下
view.translatesAutoresizingMaskIntoConstraints = NO;
  • 添加約束之前,確保所有View已經添加到父控件上
  • 設置AutoLayout之后無需再設置frame

代碼添加約束的規則

  1. 對於兄弟控件之間的約束要添加到共同的父控件上
  2. 對於不同層級的'兄弟'控件的約束要添加到最近的‘父控件’上
  3. 兩個父子控件之間的約束要添加到父控件上

下面代碼實現一個如圖自動布局
Snip20170314_21.png

    UIView * view = [UIView new];
    view.translatesAutoresizingMaskIntoConstraints = NO;
    view.backgroundColor  = [UIColor redColor];
//    view.frame = CGRectMake(10, 10, 100, 100);   ---> 不再設置frame
    [self.view addSubview:view];
    
    
    //設置底邊約束
    NSLayoutConstraint * bottomConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-10];
    
    //設置右邊約束
    NSLayoutConstraint * rightConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-10];
    
    //設置width約束
    NSLayoutConstraint * widthConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0 constant:100];
    
    //設置height約束
    NSLayoutConstraint * heightConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0 constant:100];
    
    
    [self.view addConstraint:bottomConstraint]; ----> 與父控件相關的約束添加到父控件上
    [self.view addConstraint:rightConstraint];
    [view addConstraint:widthConstraint];
    [view addConstraint:heightConstraint];

代碼實現AutoLayout相對比較繁瑣,但是如果懂得了原理還是能很好實現出來的。

AutoLayout三方框架

由於AutoLayout技術代碼實現起來特別繁瑣,並且技術含量不高、代碼冗余等問題。有一些大牛開源了一些自己寫的三方自動布局框架,使用起來非常簡單。

目前最流行的是:Masnory

至於使用方法請自行搜索、學習。

小結

  1. AutoLayout功能強大、是現在屏幕適配的首選
  2. AutoLayout在Xib上使用非常簡單靈活,代碼實現非常繁瑣
  3. 自動布局非常靈活,想要熟練需要多用多練

重要的事情多說一遍:自動布局非常靈活,想要熟練需要多用多練


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM