自动布局AutoLayout

AutoLayout

首先,使用AutoLayout就要忘了Frame的概念。

因为AutoLayout是相对布局,所以你通常不应该直接设置宽度和高度这种固定不变的值,除非你很确定视图的宽度和高度需要保持不变。

 (1)如何正确的设置宽度或高度?

    1> 如果宽度和高度布局可以改变,使用固有尺寸(intrinsic Content Size) 设置约束(size to fit size)

      2>如果宽度和高度布局不可以改变,设置约束的关系为>=

      3>调整压缩优先级和内容抗压缩优先级

    

 (2)约束是根据视图层级自上而下更新的,也就是子视图到父视图。规则:

  1>两个同层级视图的约束,添加到他们共同的父视图上

  2>两个不同层级视图的约束,添加到他们最近的共同的父视图上

  3>两个有层级关系的视图的约束,添加到层次级较高的视图上

可以通过-layoutIfNeeded和-setNeedsUpdateConstraints两个方法来刷新约束的改变,使UIView重新布局。layoutIfNeeded是调整布局,也就是view的位置,一般是对subviews作用。setNeedsDisplay涉及到redraw,也就是重绘,一般都是对receiver作用。

layoutIfNeeded

使用此方法强制立即进行layout,从当前view开始,此方法会遍历整个view层次(包括superviews)请求layout。因此,调用此方法会强制整个view层次布局。更新约束后立刻生效时使用。

setNeedsUpdateConstraints

当一个自定义view的某个属性发生改变,并且可能影响到constraint时,需要调用此方法去标记constraints需要在未来的某个点更新,系统然后调用updateConstraints.

NSLayoutConstraint方法一:

[NSLayoutConstraint constraintWithItem:(id)item
                             attribute:(NSLayoutAttribute)attribute
                             relatedBy:(NSLayoutRelation)relation
                                toItem:(id)otherItem
                             attribute:(NSLayoutAttribute)otherAttribute
                            multiplier:(CGFloat)multiplier
                              constant:(CGFloat)constant]
    参数说明:
    第一个参数:指定约束左边的视图view1
    第二个参数:指定view1的属性attr1,具体属性见文末。
    第三个参数:指定左右两边的视图的关系relation,具体关系见文末。
    第四个参数:指定约束右边的视图view2
    第五个参数:指定view2的属性attr2,具体属性见文末。
    第六个参数:指定一个与view2属性相乘的乘数multiplier
    第七个参数:指定一个与view2属性相加的浮点数constant
    
    attribut可以是上下左右宽高等等。
                            
    注意:
    1.如果你想设置的约束里不需要第二个view,要将第四个参数设为nil,第五个参数设为NSLayoutAttributeNotAnAttribute
    属性和关系的值:
    
    typedef NS_ENUM(NSInteger, NSLayoutRelation) {
        NSLayoutRelationLessThanOrEqual = -1,          //小于等于
        NSLayoutRelationEqual = 0,                     //等于
        NSLayoutRelationGreaterThanOrEqual = 1,        //大于等于
    };
    typedef NS_ENUM(NSInteger, NSLayoutAttribute) {
       NSLayoutAttributeLeft = 1,                     //左侧
       NSLayoutAttributeRight,                        //右侧
       NSLayoutAttributeTop,                          //上方
       NSLayoutAttributeBottom,                       //下方
       NSLayoutAttributeLeading,                      //首部
       NSLayoutAttributeTrailing,                     //尾部
       NSLayoutAttributeWidth,                        //宽度
       NSLayoutAttributeHeight,                       //高度
       NSLayoutAttributeCenterX,                      //X轴中心
       NSLayoutAttributeCenterY,                      //Y轴中心
       NSLayoutAttributeBaseline,                     //文本底标                                                                                                                           
       NSLayoutAttributeNotAnAttribute = 0            //没有属性
    };

实现如下效果的布局:红色、绿色、黄色View距离左右上下间距都是20,红色、绿色宽高相等,黄色高度红色,绿色相等。

  1. 关掉autoresizing的影响

    _view1.translatesAutoresizingMaskIntoConstraints = NO;

    _view2.translatesAutoresizingMaskIntoConstraints = NO;

    _view3.translatesAutoresizingMaskIntoConstraints = NO;

  2. 设置添加约束

  // view1 和 view2 的水平约束  attribute属性   relate把什么...联系起来  multiplier乘数  Layout排版,布局 Relation关系 equal相同的
    NSLayoutConstraint *view1Left = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1 constant:20];
    
    NSLayoutConstraint *view1Width = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:_view2 attribute:NSLayoutAttributeWidth multiplier:1 constant:0];
    
    NSLayoutConstraint *view1Right = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:_view2 attribute:NSLayoutAttributeLeading multiplier:1 constant:-20];
    
    NSLayoutConstraint *view2Right = [NSLayoutConstraint constraintWithItem:_view2 attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1 constant:-20];
    
    // view1 和 view3 的垂直约束
    NSLayoutConstraint *view1Top = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:20];
    
    NSLayoutConstraint *view1Height = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_view3 attribute:NSLayoutAttributeHeight multiplier:1 constant:0];
    
    NSLayoutConstraint *view1Bottom = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_view3 attribute:NSLayoutAttributeTop multiplier:1 constant:-20];
    
    NSLayoutConstraint *view3Bottom = [NSLayoutConstraint constraintWithItem:_view3 attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:-20];
    
    // view2 的垂直约束
    NSLayoutConstraint *view1CenterY = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:_view2 attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
    
    NSLayoutConstraint *view2Height = [NSLayoutConstraint constraintWithItem:_view1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_view2 attribute:NSLayoutAttributeHeight multiplier:1 constant:0];
    
    // view3 的水平约束
    
    NSLayoutConstraint *view3Left = [NSLayoutConstraint constraintWithItem:_view3 attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1 constant:20];
    
    NSLayoutConstraint *view3Right = [NSLayoutConstraint constraintWithItem:_view3 attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1 constant:-20];
    
    // 添加约束
    [self.view addConstraints:@[view1Left,view1Width,view1Right,view2Right,view1Top,view1Height,view1Bottom,view3Bottom,view1CenterY,view2Height,view3Left,view3Right]];

NSLayoutConstraint方法二:Visual Format Language(可视格式语言)

   NSDictionary *views = NSDictionaryOfVariableBindings(self.view, _view1, _view2, _view3);
    
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[_view1(_view2)]-20-[_view2]-20-|" options:NSLayoutFormatAlignAllTop|NSLayoutFormatAlignAllBottom metrics:0 views:views]];
    
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[_view3]-20-|" options:0 metrics:0 views:views]];
    
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[_view1(_view3)]-20-[_view3]-20-|" options:0 metrics:0 views:views]];

 VFL语法: 

    1. H/V表示布局方向。H表示水平方向(Horizontal),V表示垂直方向(Vertical),方向后要紧跟一个: 不能有空格! 

  2. | 表示父视图,通常出现在语句的首尾

  3. -有两个用途,单独一个表示标准距离。这个值通常是8;两个中间夹着数值,表示使用中间的数值代替标准距离。如-50-,就是使用50来代替标准距离 

  4. []表示对象,中间需要填上对象名,对象名必须是我们传入的views字典中的键。对象名后可以跟小括号(),小括号中是对对象的尺寸和优先级的约束。水平布局中尺寸是宽度,垂直布局中尺寸是高度。

@"|-50-[_view1(80@100)]-[_view2(90@200)]-50-|"
//这条语句的含义是:“左右边距都为50,中间有两个按钮,相隔缺省宽度,_view1宽度为80,约束优先级为100;_view2宽度为90,约束优先级为 200”。实际运行后,发现_view2宽度为90,而_view1的宽度为自适应宽度,并不是80像素;这是因为_view2的约束优先级 200大于_view1的约束优先级,所以优先生效。

优先级:系统内置了4个优先级

 enum{
        UILayoutPriorityRequired = 1000
        UILayoutPriorityDefaultHigh = 750,
        UILayoutPriorityDefaultLow = 250,
        UILayoutPriorityFittingSizeLevel = 50,
  }; typedef float UILayoutPriority;

  1. 优先级的取值范围0--1000,数值越大,优先被满足。

  2. 每个约束的默认优先级就是UILayoutPriorityRequired,这意味着你给出的所有约束都必须得到满足,一旦约束间发生冲突,你的应用就会Crash.这也是在使用AutoLayout时经常会犯的错误:没有给约束设置优先级。

  3. 在约束值后加@符号就可以设置优先级。

NSLayoutConstraint方法三:引用第三方库

   1. 下载Masonry 并添加到项目  包含头文件#import "Masonry.h"

  2. 代码实现

    [_view1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view).with.offset(20);
        make.leading.equalTo(self.view.mas_leading).with.offset(20);
        make.leading.equalTo(_view3);
        make.bottom.equalTo(_view3.mas_top).with.offset(-20);
        make.trailing.equalTo(_view2.mas_leading).with.offset(-20);
        make.size.equalTo(_view2);
        make.height.equalTo(_view3);
    }];
    
    [_view2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(_view1);
        make.trailing.equalTo(self.view.mas_trailing).with.offset(-20);
        make.trailing.equalTo(_view3);
    }];
    
    [_view3 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(self.view.mas_bottom).with.offset(-20);
    }];
原文地址:https://www.cnblogs.com/10-19-92/p/4888148.html