美文网首页iOS开发技术讨论iOS开发经验总结iOS
如何搞定Autolayout,远离自动布局带给你的烦恼

如何搞定Autolayout,远离自动布局带给你的烦恼

作者: Andyzhao | 来源:发表于2015-07-25 23:49 被阅读3675次

    首先让我们了解一下什么是Autolayout

    • Autolayout是一种“自动布局”技术,专门用来布局UI界面的
    • Autolayout自iOS 6开始引入,由于Xcode 4的不给力,当时并没有得到很大推广
    • 自iOS 7(Xcode 5)开始,Autolayout的开发效率得到很大的提升
    • 苹果官方也推荐开发者尽量使用Autolayout来布局UI界面
    • Autolayout能很轻松地解决屏幕适配的问题

    (一)下面让我们用例子来进一步了解Autolayout

    示例如下:


    效果图.png

    代码实现Autolayout的步骤

    • 利用NSLayoutConstraint类创建具体的约束对象
    • 添加约束对象到相应的view上
      - (void)addConstraint:(NSLayoutConstraint *)constraint;
      - (void)addConstraints:(NSArray *)constraints;
    

    代码实现Autolayout的注意点

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

    创建约束对象的常用方法

    创建约束对象的常用方法
    +(id)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
    view1 :要约束的控件
    attr1 :约束的类型(做怎样的约束)
    relation :与参照控件之间的关系
    view2 :参照的控件
    attr2 :约束的类型(做怎样的约束)
    multiplier :乘数
    c :常量
    

    要用苹果的方法代码实现如下:(额,敲得我【恶心他妈给恶心开门----恶习到家了,不过不要担心请接着往下看】)

    
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        UIView *blueView = [[UIView alloc] init];
        blueView.backgroundColor = [UIColor blueColor];
        // 禁止Autoresizing转为Autolayout的约束
        blueView.translatesAutoresizingMaskIntoConstraints = NO;
        [self.view addSubview:blueView];
        
        
        UIView *redView = [[UIView alloc] init];
        redView.backgroundColor = [UIColor redColor];
        // 禁止Autoresizing转为Autolayout的约束
        redView.translatesAutoresizingMaskIntoConstraints = NO;
        [self.view addSubview:redView];
     
        // 添加蓝色控件的约束
        NSLayoutConstraint *blueLeftLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:20];
           [self.view addConstraint:blueLeftLc];
        NSLayoutConstraint *blueBottomLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-20];
        [self.view addConstraint:blueBottomLc];
        
        NSLayoutConstraint *buleRightLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:redView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-20];
        [self.view addConstraint:buleRightLc];
        
        NSLayoutConstraint *blueHLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:40];
        [self.view addConstraint:blueHLc];
        
        NSLayoutConstraint *blueWidthLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:redView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0];
        [self.view addConstraint:blueWidthLc];
    
        /*** 添加红色控件的约束 ***/
        NSLayoutConstraint *redTopLc = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
        [self.view addConstraint:redTopLc];
        
        NSLayoutConstraint *redBottomLc = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
        [self.view addConstraint:redBottomLc];
        
        NSLayoutConstraint *redRightLc = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-20];
        [self.view addConstraint:redRightLc];
    }
    
    
    @end
    
    

    OK看到就这么一个简单的效果要这么多代码,是不是想要抓狂,不要心慌,下面我们介绍目前最流行的Autolayout第三方框架---Masonry

    同样的让我们先大致了解一个Masonry的一些情况

    • 目前最流行的Autolayout第三方框架

    • 用优雅的代码方式编写Autolayout

    • 省去了苹果官方恶心的Autolayout代码

    • 大大提高了开发效率

    • 框架地址:
      https://github.com/SnapKit/Masonry

    上面的效果图用Masonry实现如下:

    #import "ViewController.h"
    
    //define this constant if you want to use Masonry without the 'mas_' prefix
    #define MAS_SHORTHAND
    
    //define this constant if you want to enable auto-boxing for default syntax
    #define MAS_SHORTHAND_GLOBALS
    
    #import "Masonry.h"
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        // 创建蓝色View
        UIView *blueView = [[UIView alloc] init];
        blueView.backgroundColor = [UIColor blueColor];
        [self.view addSubview:blueView];
        
        // 创建红色View
        UIView *redView = [[UIView alloc] init];
        redView.backgroundColor = [UIColor redColor];
        [self.view addSubview:redView];
        
        // 给蓝色View添加约束
        [blueView makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self.view.left).offset(20);
            make.bottom.equalTo(self.view.bottom).offset(-20);
            make.right.equalTo(redView.left).offset(-20);
            make.height.equalTo(40);
            make.width.equalTo(redView.width);
            
        }];
        
        // 给红色View添加约束
        [redView makeConstraints:^(MASConstraintMaker *make) {
            make.right.equalTo(self.view.right).offset(-20);
            make.top.equalTo(blueView.top);
            make.bottom.equalTo(blueView.bottom);
       
        }];
        
        // 更新约束
        [blueView updateConstraints:^(MASConstraintMaker *make) {
            make.height.equalTo(80);
        }];
    }
    
    @end
    
    
    

    上面这段代码是不是让你的心情大爽了呢,激动之余细心的读者可能发现,咦#import "Masonry.h"上面怎么有两个宏呢,下面我们来了解一下这是为什么呢

    首先是Masonry中的mas_equalToequalTo

    • 默认情况下

      • mas_equalTo有自动包装功能,比如自动将20包装为@20
      • equalTo没有自动包装功能
    • 如果添加了下面的宏,那么mas_equalTo和equalTo就没有区别

    #define MAS_SHORTHAND_GLOBALS
    // 注意:这个宏一定要添加到#import "Masonry.h"前面
    

    其次是Masonry中的mas_widthwidth

    • 默认情况下

      • width是make对象的一个属性,用来添加宽度约束用的,表示对宽度进行约束
      • mas_width是一个属性值,用来当做equalTo的参数,表示某个控件的宽度属性
    • 如果添加了下面的宏,mas_width也可以写成width

     #define MAS_SHORTHAND
    
     mas_height、mas_centerX以此类推
    

    总之这样简单高效的方法让我们程序员用的好爽不是吗

    (二)开发中我们会遇到这样的问题- 使用到约束的优先级

    • 为了大家更方便的学习我就不用代码实现了,在Storyboard中添加约束
    • 先看一下效果图
    // 点击屏幕时会调用此方法
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        //
        [self.blueView removeFromSuperview];
        // 利用2s的时间去更新约束,在修改了约束之后,只要执行下面代码,就能做动画效果,感兴趣的读者可以试一下
        [UIView animateWithDuration:2 animations:^{
          
            // 强制更新约束(让self.view以及它的所有子控件都强制更新)
            [self.view layoutIfNeeded];
        }];
       
    }
    
    约束优先级.gif

    OK这样的效果怎么实现呢,给大家看两张图大家就明白约束优先级的用处了

    • 绿色与蓝色的约束优先级值


      绿色与蓝色的约束优先级值.png
    • 绿色与红色的约束优先级值
    绿色与红色的约束优先级值.png
    • 从上面可以看出绿色与蓝色的约束优先级值大于绿色与红色的约束优先级值,所以当3个View都存在时执行绿色与蓝色的约束优先级值,
      当点击屏幕,移除绿色View时绿色与蓝色的约束优先级值无效了,执行绿色与红色的约束优先级值,故此可以实现以上效果

    谢谢各位耐心观看,如有问题请留言我会及时更新改正,谢谢大家,祝各位每天开心!!!

    相关文章

      网友评论

      • 贺彦文:如果是cell的话 重利用是个问题.例如 第一个cell需要去掉蓝色view,第二个cell需要加上蓝色.去掉再加回来的蓝色view恐怕约束都不在了吧
        咖穆:cell 里重用, 就不要把蓝view 简单粗暴的remove 掉了,动态设置绿与蓝之间约束的优先级应该就可以了,当不需要显示蓝view 的时候把这个约束设置为最低,绿就会跑到蓝的位置,然后把蓝给隐藏掉就可以了.当然不在cell 里用,也最好不要把蓝view remove掉,会有内存问题.
        祖宗:@贺彦文 正解,cell还是乖乖手写省事
      • 阿丰在长春:更好的布局方法是恒久的话题。
      • 0d48debc0995:感觉在anyany里面构建布局更便捷一些,这个第三方还没用过,以前纯代码手写的,很好的分享,👍一个哈。

      本文标题:如何搞定Autolayout,远离自动布局带给你的烦恼

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