iOS學習之自動佈局

Autolayout:

最重要的兩個概念

  • 約束:對控件位置和大小的限定條件
  • 參照:對控件設置的約束是相對於哪個視圖而言的

自動佈局的核心計算公式

obj1.property1 =(obj2.property2 * multiplier)+ constant valuegit

解釋:obj1的property1屬性等於obj2的property2屬性乘以multiplier(係數)再加constant(常量);github

約束的優先級:

約束的priority屬性表示約束的優先級,取值區間爲[0,1000],默認爲1000。priority值越大,表示優先級越高,會優先執行。優先級低的約束只有在優先級較高的約束失效後纔會執行。數組

警告和錯誤:

在使用storyboard和xib設置約束時,約束有可能會變成黃色或者紅色。當發生這樣的狀況時,就說明設置的約束有問題。框架

  • 若是約束是黃色的,這只是一個警告,表明控件的frame和設置的約束不相符,更新frame或者更新約束就能夠解決。
  • 若是約束是紅色的,這就表明錯誤,約束設置不徹底或者某兩個約束有衝突,只有約束設置完整而且沒有衝突,紅色錯誤提示纔會消失。

添加約束的3條規則:

  • 對於兩個同層級View之間的約束關係,應該添加到它們的父View之上。
    同層級的View
  • 對於兩個不一樣層級View之間的約束關係,應該添加到它們最近的共同父View上。
    不一樣層級的View
  • 對於有層次關係的兩個view之間的約束關係,添加到層次較高的父view上
    有層級關係的View

代碼實現Autolayout:

代碼實現Autolayout須要注意:ide

  • 必須先禁止autoresizing功能,設置View的下面屬性爲NO
    view.translatesAutoresizingMaskIntoConstraints = NO;
  • 添加約束以前,必定要保證相關控件都已經添加到各自的父控件上了
  • 不用再給View設置frame

利用NSLayoutConstraint類建立具體的約束對象

添加約束到相應的View上:佈局

- (void)addConstraint:(NSLayoutConstraint *)constraint;
- (void)addConstraints:(NSArray *)constraints;

NSLayoutConstraint:

一個NSLayoutConstraint對象就表明一個約束,能夠經過修改NSLayoutConstraint對象的屬性來修改約束。動畫

建立約束對象經常使用的方法:ui

/**
 *  添加一個約束,其實就是根據公式來計算約束
 *  obj1.property1 =(obj2.property2 * multiplier)+ constant value
 *  @param view1      須要添加約束的View
 *  @param attr1      須要添加的約束(左邊、右邊、長寬仍是。。。)
 *  @param relation   約束關係(大於、等於仍是小於)
 *  @param view2      參照View(約束是相對於哪一個View而言)
 *  @param attr2      參照View的哪個參數(左邊、右邊、長寬仍是。。。)
 *  @param multiplier 係數
 *  @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;

示例:spa

UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];

//關閉Autoresizing
blueView.translatesAutoresizingMaskIntoConstraints = NO;

//建立左邊約束
NSLayoutConstraint *leftLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:20];
[self.view addConstraint:leftLc];

//建立右邊約束
NSLayoutConstraint *rightLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-20];
[self.view addConstraint:rightLc];

//建立底部約束
NSLayoutConstraint *bottomLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-20];
[self.view addConstraint:bottomLc];

//建立高度約束
NSLayoutConstraint *heightLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:50];
[blueView addConstraint: heightLc];

效果圖:
豎屏效果code

橫屏效果

使用VFL語句添加約束:

使用VFL來建立約束數組:

/**
*  使用VFL語句來建立約束數組
*
*  @param format  VFL語句
*  @param opts    約束類型
*  @param metrics VFL語句中用到的具體數值
*  @param views   VFL語句中用到的控件
*
*  @return 返回建立好的約束數組
*/
+ (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(nullable NSDictionary<NSString *,id> *)metrics views:(NSDictionary<NSString *, id> *)views;

VFL語句示例:

H:[cancelButton(72)]-12-[acceptButton(50)]
canelButton寬72,acceptButton寬50,它們之間間距12

H:[wideView(>=60@700)]
wideView寬度大於等於60point,該約束條件優先級爲700(優先級最大值爲1000,優先級越高的約束越先被知足)

V:[redBox][yellowBox(==redBox)]
豎直方向上,先有一個redBox,其下方緊接一個高度等於redBox高度的yellowBox

H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|
水平方向上,Find距離父view左邊緣默認間隔寬度,以後是FindNext距離Find間隔默認寬度;再以後是寬度不小於20的FindField,它和FindNext以及父view右邊緣的間距都是默認寬度。(豎線「|」 表示superview的邊緣)

VFL代碼示例:

// 建立藍色View
    UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:blueView];

    // 建立紅色View
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:redView];

    // VFL建立約束
    // 水平方向
    NSString *VFL_H = @"H:|-space-[blueView]-space-[redView(==blueView)]-space-|";
    NSDictionary *metrics = @{
                              @"space" : @30,
                              };
    //    NSDictionary *views = @{
    //                            @"blueView" : blueView,
    //                            @"redView" : redView
    //                            };
    NSDictionary *views = NSDictionaryOfVariableBindings(blueView,redView);

    NSArray *arrayH = [NSLayoutConstraint constraintsWithVisualFormat:VFL_H options:NSLayoutFormatAlignAllTop metrics:metrics views:views];
    [self.view addConstraints:arrayH];

    // 垂直方向
    NSString *VFL_V = @"V:[blueView(50)]-space-|";
    NSArray *arrayV = [NSLayoutConstraint constraintsWithVisualFormat:VFL_V options:kNilOptions metrics:metrics views:views];
    [self.view addConstraints:arrayV];

    // 添加紅色View的約束
    // 添加高度約束
    NSLayoutConstraint *redV_height = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0];
    [self.view addConstraint:redV_height];

效果圖:
豎屏效果
橫屏效果

Masonry的使用:

Masonry是目前最流行的Autolayout第三方框架,讓你能夠用簡單的代碼來編寫Autolayout,省去了蘋果官方繁複的Autolayout代碼,大大提高了開發效率。

mas_equalToequalTo

默認狀況下mas_equalTo有自動包裝功能,好比自動將20包裝爲@20equalTo沒有自動包裝功能。

若是添加了下面的宏,那麼mas_equalToequalTo就沒有區別:

#define MAS_SHORTHAND_GLOBALS
// 注意:這個宏必定要添加到#import "Masonry.h"前面

mas_widthwidth:

默認狀況下
widthmake對象的一個屬性,用來添加寬度約束用的,表示對寬度進行約束。mas_width是一個屬性值,用來當作equalTo的參數,表示某個控件的寬度屬性。

若是添加了下面的宏,mas_width也能夠寫成width:
#define MAS_SHORTHAND

mas_heightmas_centerX以此類推。

下面用Masonry框架實現一下上面VFL語句的示例,對比一下就會發現有了Masonry框架之後自動佈局變得多麼容易:

//建立藍色控件
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];

//建立紅色控件
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];

// 添加blueView的約束
[blueView makeConstraints:^(MASConstraintMaker *make) {
    make.width.equalTo(redView.width).offset(0);
    make.height.equalTo(redView.height).offset(0);
    make.height.equalTo(100);
    make.left.equalTo(blueView.superview.left).offset(20);
    make.bottom.equalTo(blueView.superview.bottom).offset(-20);
    make.right.equalTo(redView.left).offset(-20);
}];

// 添加redView的約束
[redView makeConstraints:^(MASConstraintMaker *make) {
    make.bottom.equalTo(redView.superview.bottom).offset(-20);
    make.right.equalTo(redView.superview.right).offset(-20);
}];

Masonry框架提供了不少示例程序,感興趣的能夠打開上面GitHub的連接下載下來仔細研究,這裏就很少寫了。
GitHub連接爲:https://github.com/SnapKit/Masonry

約束動畫:

在執行動畫時記得調用如下方法:

//在修改了約束以後,只要執行下面代碼,約束就能作出動畫效果
[UIView animateWithDuration:0.5 animations:^{
      [self.view layoutIfNeeded];
  }];

使用Autolayout實現UILabel內容包裹:

  • 一、設置UILabel的位置約束
  • 二、設置label.numberOfLines = 0;,使label可以自動換行來計算高度
  • 三、代碼建立約束時,應設置label的最大寬度preferredMaxLayoutWidth
相關文章
相關標籤/搜索