美文网首页iOS开发随笔iOS开发iOS学习笔记
Autolayout进阶之代码编写约束(一)

Autolayout进阶之代码编写约束(一)

作者: o翻滚的牛宝宝o | 来源:发表于2016-07-08 17:55 被阅读221次

    在我看来,Autolayout是开发神器,但是它也有局限之处。拿cell来举例,如果cell中的控件个数不确定,根据后台所给的数据来控制显示控件个数,那么Autolayout就不能简单的在xib上“拖”出来,而需要在代码中编写。这种情况在实际开发中是很常见的。我们再来看看原生代码的手写约束:

    NSLayoutConstraint* leftConstraint = [NSLayoutConstraint constraintWithItem:logoImageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.0f constant:0.0f];
    
    //logoImageView右侧与父视图右侧对齐
    NSLayoutConstraint* rightConstraint = [NSLayoutConstraint constraintWithItem:logoImageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1.0f constant:0.0f];
    
    //logoImageView顶部与父视图顶部对齐
    NSLayoutConstraint* topConstraint = [NSLayoutConstraint constraintWithItem:logoImageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f];
    
    //logoImageView高度为父视图高度一半
    NSLayoutConstraint* heightConstraint = [NSLayoutConstraint constraintWithItem:logoImageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:0.5f constant:0.0f];
    
    //iOS 6.0或者7.0调用addConstraints
    //[self.view addConstraints:@[leftConstraint, rightConstraint, topConstraint, heightConstraint]];
    

    是不是很难记?和frame相比,也变得更抽象,代码量也更多。谁会愿意摆放一个控件写那么多代码?幸运的是,现在我们有很多第三方框架来帮我们简化这些代码。

    Masonry和SDAutolayout


    目前网上流行AutoLayout框架主要是Masonry和SDAutolayout。前者是我目前项目中常用的框架,主要是用block回调,并且将复杂的约束讲话成MASConstraintMaker进行约束封装。后者是声称比Masonry更简单易用的约束框架,采用链式编程的思想对约束进行封装,并能实现cell高度自适应。下面我们来看看具体的使用方法。

    Masonry框架

    • Masonry是公认非常简洁优美的一款Autolayout框架
    • gitHub地址:https://github.com/SnapKit/Masonry
    • 推荐用cocoapods安装(如果不知道还是网上搜索下,开发必备)pod search Masonry
    • 非常适合拿来练手

    首先#import "Masonry.h"导入头文件,然后就可以用代码进行约束编写:

    //初始化一个view
    UIView * redView = [[UIView alloc]init];
    redView.backgroundColor = [UIColor redColor];
    //然后将这个view添加到界面上
    [self.view addSubview:redView];
    //然后进行约束设置
    [redView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.view).offset(100);
        make.right.equalTo(self.view).offset(-200);
        make.top.equalTo(self.view).offset(100);
        make.height.mas_equalTo(100);
    }];
    

    先看这一段代码,首先创建了一个UIView,将背景色设成红色,然后进行约束设置。Masonry的命名都很直观,唯一要解释的可能就是这个make。我们可以理解成这个make就是redView本身,make.left.equalTo(self.view).offset(100);就是设置redView的左侧相对于self.view偏移量为100。这种思想和在xib上拖线的思想是一致的。再来看看设置自己本身高度的约束make.height.mas_equalTo(100);和上面一条唯一的区别就是mas_equalTo。还有一点需要注意的是.offset的值,如果前面是make.left(或者make.leading)和make.top,那么offset中设置的值为正数,如果是make.right(或者make.trailing)和make.bottom,那么offset中的值设成负数。
    我们都知道,约束都有优先级。在Masonry语法中设置优先级也很简单,make.height.mas_equalTo(100).priority(500);只要在后面添上.priority(优先级)就行了,如果不添加,默认优先级为1000。

    单个红色控件约束效果

    再看另外一个例子:

    //初始化一个view
    UIView * redView = [[UIView alloc]init];
    redView.backgroundColor = [UIColor redColor];
    UIView * greenView = [[UIView alloc]init];
    greenView.backgroundColor = [UIColor greenColor];
    //然后将这个view添加到界面上
    [self.view addSubview:redView];
    [self.view addSubview:greenView];
    
    //然后进行约束设置
    [redView mas_makeConstraints:^(MASConstraintMaker *make) {
       
        make.left.equalTo(self.view).offset(100);
        make.right.equalTo(greenView.mas_left).offset(-50);
        make.top.equalTo(self.view).offset(100);
        make.height.mas_equalTo(100).priority(500);
    }];
    
    [greenView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.equalTo(self.view).offset(-30);
        make.top.equalTo(self.view).offset(100);
        make.height.mas_equalTo(100);
        make.width.mas_equalTo(100);
    }];
    

    这里要注意的是make.right.equalTo(greenView.mas_left).offset(-50);这个写法,中间的括号是greenView.mas_left,应该也很好理解。
    效果:

    两个控件手写约束效果

    关于mas_makeConstraintsmas_updateConstraintsmas_remakeConstraints的用法都是相同的,官方的API文档是这样描述的:

    /**
     *  Creates a MASConstraintMaker with the callee view.
     *  Any constraints defined are added to the view or the appropriate superview once the block has finished executing
     *
     *  @param block scope within which you can build up the constraints which you wish to apply to the view.
     *
     *  @return Array of created MASConstraints
     */
    - (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;
    
    /**
     *  Creates a MASConstraintMaker with the callee view.
     *  Any constraints defined are added to the view or the appropriate superview once the block has finished executing.
     *  If an existing constraint exists then it will be updated instead.
     *
     *  @param block scope within which you can build up the constraints which you wish to apply to the view.
     *
     *  @return Array of created/updated MASConstraints
     */
    - (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block;
    
    /**
     *  Creates a MASConstraintMaker with the callee view.
     *  Any constraints defined are added to the view or the appropriate superview once the block has finished executing.
     *  All constraints previously installed for the view will be removed.
     *
     *  @param block scope within which you can build up the    constraints which you wish to apply to the view.
     *
        *  @return Array of created/updated MASConstraints
     */
        - (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block;
    

    总的来说,mas_makeConstraints就是在原基础上添加约束,mas_updateConstraints就是更新约束,mas_remakeConstraints就是先去除原有约束再添加约束

    总结

    • 先把要添加约束的控件add到父视图上(addSubview)
    • 使用mas_makeConstraints添加约束,make可以设想成这个控件本身
    • 如果是添加左侧或者上侧的约束,offset用正数,如果添加右侧和下侧的约束,offset用负数
    • 设置本身的约束(height、width)用mas_equalTo
    • 如果两个平级控件之间设置约束,第二个控件要带上(mas_方向)

    我是翻滚的牛宝宝,欢迎大家评论交流~

    相关文章

      网友评论

      本文标题:Autolayout进阶之代码编写约束(一)

      本文链接:https://www.haomeiwen.com/subject/ezqrjttx.html