• iOS自动布局的学习


    Autolayout:

    最重要的两个概念

    • 约束:对控件位置和大小的限定条件
    • 参照:对控件设置的约束是相对于哪一个视图而言的

    自动布局的核心计算公式:

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

    解释:obj1的property1属性等于obj2的property2属性乘以multiplier(系数)再加constant(常量);

    约束的优先级:

    约束的priority属性表示约束的优先级,取值区间为[0,1000],默认为1000。priority值越大,表示优先级越高,会优先执行。优先级低的约束只有在优先级较高的约束失效后才会执行。

    警告和错误:

    在使用storyboard和xib设置约束时,约束有可能会变成黄色或者红色。当发生这样的情况时,就说明设置的约束有问题。

    • 如果约束是黄色的,这只是一个警告,代表控件的frame和设置的约束不相符,更新frame或者更新约束就可以解决。
    • 如果约束是红色的,这就代表错误,约束设置不完全或者某两个约束有冲突,只有约束设置完整并且没有冲突,红色错误提示才会消失。

    添加约束的3条规则:

    • 对于两个同层级View之间的约束关系,应该添加到它们的父View之上。
     
    同层级的View
    • 对于两个不同层级View之间的约束关系,应该添加到它们最近的共同父View上。


       
      不同层级的View
    • 对于有层次关系的两个view之间的约束关系,添加到层次较高的父view上
     
    有层级关系的View

    代码实现Autolayout:

    代码实现Autolayout需要注意:

    • 必须先禁止autoresizing功能,设置View的下面属性为NO
      view.translatesAutoresizingMaskIntoConstraints = NO;
    • 添加约束之前,一定要保证相关控件都已经添加到各自的父控件上了
    • 不用再给View设置frame

    利用NSLayoutConstraint类创建具体的约束对象

    添加约束到相应的View上:

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

    NSLayoutConstraint:

    一个NSLayoutConstraint对象就代表一个约束,可以通过修改NSLayoutConstraint对象的属性来修改约束。

    创建约束对象常用的方法:

    /**
     *  添加一个约束,其实就是根据公式来计算约束
     *  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;
    示例:
    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];
    //(这里需要注意一下,blueview的右边界相对于self.view右边的界位置是负数,同理底部(bottom)也是负数)
    //创建底部约束
    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];
    //这里需要注意一下,
    NSLayoutAttributeHeight是没有参照视图的。因此toItem为nil mutiplier为0。
    
    

    效果图:


     
    竖屏效果
     
    横屏效果

    使用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-|";//注意:这里V:的后面紧接着是[blueView(50)]并没有“|”。说明对距顶部的距离未做约束
        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内容包裹:

    • 1、设置UILabel的位置约束
    • 2、设置label.numberOfLines = 0;,使label能够自动换行来计算高度
    • 3、代码创建约束时,应设置label的最大宽度preferredMaxLayoutWidth



    作者:真一
    链接:https://www.jianshu.com/p/d52fb0d3ea15

  • 相关阅读:
    项目
    关于我
    【转载】罗胖精选|什么样的自控方法才有效?
    知识管理——得到CEO脱不花女士的一次分享
    注意由双大括号匿名类引起的serialVersionUID编译告警
    持续集成、持续交付和持续部署
    Google Cayley图数据库使用方法
    任务的属性
    团队博客地址
    个人总结
  • 原文地址:https://www.cnblogs.com/OIMM/p/8875169.html
Copyright © 2020-2023  润新知