iOS原生自動佈局NSLayoutConstraint

AutoLayout概念是蘋果自iOS6開始引入的概念。

目前爲止,實現自動佈局技術選型方面也可使用xib和storyboard。在開發過程當中一般登陸、註冊等變更可能性較小的視圖,我會採用xib開發,其餘頁面一般會採用Masonry佈局。xib和手碼各有優點,視狀況而定。
 
關於NSLayoutAttributeLeading和NSLayoutAttributeTrailing,前邊和後邊並非老是爲左邊和右邊的,有些國家的前邊是右邊後邊是左邊因此這樣設定是爲了國際化考慮。還有視圖基準線NSLayoutAttributeBaseline一般是指視圖的底部放文字的地方。
 
使用NSLayoutConstraint以前,咱們須要肯定一點:爲了防止constraint和view自己的autoresizing屬性衝突,咱們須要設置view的屬性:
view.translatesAutoresizingMaskIntoConstraints = NO;

1、UIKit框架提供的自動佈局的方法一,詳細請看參數介紹:框架

複製代碼
/**
 設置約束

 @param view1 指定須要添加約束的視圖一
 @param attr1 指定視圖一須要約束的屬性
 @param relation 指定視圖一和視圖二添加約束的關係
 @param view2 指定視圖一依賴關係的視圖二;可爲nil
 @param attr2 指定視圖一所依賴的視圖二的屬性,若view2=nil,該屬性設置 NSLayoutAttributeNotAnAttribute
 @param multiplier 係數   狀況一和二爲親測
                 狀況一:設置A視圖的高度 = A視圖高度 * multiplier + constant;此時纔會起做用;
                 狀況二:設置A視圖和其餘視圖的關係或 toItem=nil,multiplier設置不等於0便可,若等於0會crash;
 @param c 常量
 @return 返回生成的約束對象
 */
+ (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
複製代碼

以上函數設置的約束等價於   view1.att1 =(以等號舉栗子,relation可> < ≥≤)view2.attr2 * multiplier + c;函數

簡單小需求:隨意在控制器中添加一個紅色view:佈局

複製代碼
// 設置 redView 的寬 = 100.f * 1.f
    NSLayoutConstraint *redViewWidthConstraint =
    [NSLayoutConstraint constraintWithItem:self.redView
                                 attribute:NSLayoutAttributeWidth
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:nil
                                 attribute:NSLayoutAttributeNotAnAttribute
                                multiplier:1.f
                                  constant:100.f];
    // 設置 redView 的高 = 100.f * 1.f
    NSLayoutConstraint *redViewHeightConstraint =
    [NSLayoutConstraint constraintWithItem:self.redView
                                 attribute:NSLayoutAttributeHeight
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:nil
                                 attribute:NSLayoutAttributeNotAnAttribute
                                multiplier:1.f
                                  constant:100.f];
    // 設置 redView 的前面(左邊) = self.view.leading + 20.f
    NSLayoutConstraint *redViewleadingConstraint =
    [NSLayoutConstraint constraintWithItem:self.redView
                                 attribute:NSLayoutAttributeLeading
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:self.view
                                 attribute:NSLayoutAttributeLeading
                                multiplier:1.f
                                  constant:20.f];
    
    // 設置 redView 的頂部
    NSLayoutConstraint *redViewTopConstraint =
    [NSLayoutConstraint constraintWithItem:self.redView
                                 attribute:NSLayoutAttributeTop
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:self.view
                                 attribute:NSLayoutAttributeTop
                                multiplier:1.f
                                  constant:30.f];
    [self.view addConstraint:redViewWidthConstraint];
    [self.view addConstraint:redViewHeightConstraint];
    [self.view addConstraint:redViewleadingConstraint];
    [self.view addConstraint:redViewTopConstraint];
複製代碼

 

 

小注:
一、關於參數  multiplier 
複製代碼
✅舉個栗子🌰:
     [NSLayoutConstraint constraintWithItem:aView
     attribute:NSLayoutAttributeHeight
     relatedBy:NSLayoutRelationEqual
     toItem:aView
     attribute:NSLayoutAttributeWidth
     multiplier:2.f
     constant:100.f];
     等價於  aView的高 = aView的寬 * 2.f + 100.f;
複製代碼

 

二、❌原本想逃懶,下面的寫法,通過我實驗是錯誤的post

複製代碼
     [NSLayoutConstraint constraintWithItem:self.redView
     attribute:NSLayoutAttributeWidth | NSLayoutAttributeHeight
     relatedBy:NSLayoutRelationEqual
     toItem:nil
     attribute:NSLayoutAttributeNotAnAttribute
     multiplier:1.f
     constant:100.f];
複製代碼

 

2、UIKit框架提供的自動佈局的方法二,VFL語言來實現自動佈局:spa

複製代碼
/**
 Description

 @param format VFL語句,舉個栗子:@"H:|-[_redView]-padding-|"
 @param opts 枚舉參數,默認寫0
 @param metrics 字典,key值爲VFL語句中的變量 padding,value爲指定的值: @{@"padding" : @50}
 @param views VFL語句中使用到的視圖
 */

+ (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(nullable NSDictionary<NSString *,id> *)metrics views:(NSDictionary<NSString *, id> *)views;
複製代碼
複製代碼
舉個栗子:
NSArray *constraints1 =
    [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_redView]-padding-|"
                                            options:0
                                            metrics:@{@"padding" : @50}
                                              views:NSDictionaryOfVariableBindings(_redView)];
    NSArray *constraint2 =
    [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-height-[_redView(height)]"
                                            options:0
                                            metrics:@{@"height" : @20}
                                              views:NSDictionaryOfVariableBindings(_redView)];
    [self.view addConstraints:constraints1];
    [self.view addConstraints:constraint2];
複製代碼

 

關於UILabel自動佈局,須要注意的是若label多行顯示,可經過設置numberOfLines:code

複製代碼
UILabel *label = [[UILabel alloc] init];
    label.translatesAutoresizingMaskIntoConstraints = NO;
    label.text = @"Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~Label~~";
    label.textColor = [UIColor blackColor];
    label.backgroundColor = [UIColor redColor];
    label.numberOfLines = 0;
    [self.view addSubview:label];
    
    NSArray *labelConstraintsH =
    [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[label]-20-|"
                                            options:0
                                            metrics:nil
                                              views:NSDictionaryOfVariableBindings(label)];
    NSArray *labelConstraintsV =
    [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-30-[label]"
                                            options:0
                                            metrics:nil
                                              views:NSDictionaryOfVariableBindings(label)];
    [self.view addConstraints:labelConstraintsH];
    [self.view addConstraints:labelConstraintsV];
複製代碼

 

注意:
     一、VFL語句中具體浮點型不可使用 56.f 諸如此類,會crash;
     二、VFL語句中的視圖,不要使用self.xxx屬性,而要使用變量_xxx,會crash
     三、addConstraint以前,必須保證subView已擁有superView
     四、視圖的 translatesAutoresizingMaskIntoConstraints 必須設置爲NO,
   五、一般使用的是Masonry\SnapKit自動佈局的三方庫,簡單高效。校之frame佈局,自動佈局更適合業務拓展。 
相關文章
相關標籤/搜索