目前爲止,實現自動佈局技術選型方面也可使用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佈局,自動佈局更適合業務拓展。