NSLayoutContraint的使用

一、介绍

说起自动布局,什么masonry或者sd_autolayout等三方库,都是基于原生的NSLayoutContraint来写的,所以有必要知道NSLayoutContraint这个东西。

二、发展史

1、屏幕适配发展的路线:

1)纯代码计算frame(最早是通过计算frame实现布局)
2)autoresizing(仅适用于约束父子控件之间的关系)
3)AutoLayout(iOS6/2012年、iPhone5被引入,比autoresizing更加高级,旨在替代autoresizing,可以设置任何控件之间的关系)
4)sizeClass(iOS8出现,用于解决越来越多的屏幕尺寸的适配问题)。

2、为什么总是在变换屏幕布局的方式?
iPhone3gs时代,手机的屏幕尺寸有且只有一种,也就是3.5英寸。开发app的时候,根本不用考虑同一个视图在不同尺寸的屏幕上显示的问题。iOS开发者完全可以**用纯代码的方式**把一个控件的frame写死。而后来随着苹果公司的不断推出新机型,随着屏幕的尺寸变大和布局时候的复杂程度越来越大,在使用写死frame的方法是满足不了需求的,所以最后苹果公司为了开发者能够更好的工作就逐渐推出了autoresizing,AutoLayout(iOS6.0),sizeClass(iOS).

三、Autoresizing

Xcode5之后,新建的项目默认使用AutoLayout。Autoresizing默认不启用,我们可以去掉use Auto Layout,Use Size Classes前面的对勾来启用Autoresizing,如下图:


UIView的autoresizesSubviews是YES时(默认是YES), 那么在其中的子view会根据它自身的autoresizingMask属性来自动适应其与superView之间的位置和大小。通俗易懂的话语来讲就是:当父视图被拉伸的时候,子视图能够适配父视图的新大小。其原理是,子视图有一个masks,用于指定与父视图上下左右边缘的距离,以及自身宽高的关系。比如,指定子视图的右边缘紧跟着父视图的右边缘,那么父视图变大之后,子视图还是贴在父视图的右边。这在大部分简单布局情况下非常有效


四、Autolayout

1、AutolayoutContraint

AutoLayout是从IOS 6开始苹果引入来取代autoresizing的新的布局技术,该技术有三种设置方式,在说三种设置方式前,我们先简单的说一下autolayout能够设置哪些行为。
1)视图的大小(即视图的绝对大小)。
2)视图的位置(视图相对于父视图或者兄弟视图的位置)。
3)视图的对齐方式(相对于父视图或者相对于兄弟视图)。

可以看到autolayout相比autoresizing技术来说要灵活的多,该技术有很多布局的约束设置。这次主要讲的用代码来设置AutoLayout,必须要注意的是在使用 Auto Layout 时,首先需要将视图的 setTranslatesAutoresizingMaskIntoConstraints 属性设置为 NO。这个属性默认为 YES。当它为 YES 时,运行时系统会自动将 Autoresizing Mask 转换为 Auto Layout 的约束,这些约束很有可能会和我们自己添加的产生冲突。代码向我们需要添加autoLayout视图使用该方法:

+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c

#pragma mark -methodOne
- (void)methodOne{
    
    _redV = [[UIView alloc] initWithFrame:CGRectZero];
    _redV.backgroundColor = [UIColor redColor];
    [self.view addSubview:_redV];
    
    //为了防止constraint和view的zutoresizing属性冲突,我们需要设置view的属性
    self.redV.translatesAutoresizingMaskIntoConstraints = NO;
    
    /*
     @param item1 指定需要添加约束的视图一
     @param attribute 指定视图一需要约束的属性
     @param relatedBy 指定个视图一和视图二添加约束的关系
     @param item2 指定视图一依赖关系的视图二,可为nil
     @param attribute 指定视图一所依赖的视图二的属性,若view2 = nil,该属性设置NSLayoutAttributeNotAnAttribute
     @param multiplier 系数 情况一:设置A视图的高度 = A视图高度 * multiplier + constant;此时才会起作用;
     情况二:设置A视图和其他视图的关系或 toItem=nil,multiplier设置不等于0即可,若等于0会crash;
     @param
     */
    //设置redView的宽 = 100.f
    NSLayoutConstraint * readViewW = [NSLayoutConstraint constraintWithItem:self.redV
                                                                  attribute:NSLayoutAttributeWidth
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:nil
                                                                  attribute:NSLayoutAttributeNotAnAttribute
                                                                 multiplier:1.f
                                                                   constant:100.f];
    //设置readView的高 = 100.f
    NSLayoutConstraint * readViewH = [NSLayoutConstraint constraintWithItem:self.redV
                                                                  attribute:NSLayoutAttributeHeight
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:nil
                                                                  attribute:NSLayoutAttributeNotAnAttribute
                                                                 multiplier:1.0
                                                                   constant:100.f];
    //设置readView的左 = 20.f
    NSLayoutConstraint * readViewL = [NSLayoutConstraint constraintWithItem:self.redV
                                                                  attribute:NSLayoutAttributeLeading
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:self.view
                                                                  attribute:NSLayoutAttributeLeading
                                                                 multiplier:1.f
                                                                   constant:20.f];
    //设置readView的上 = 50.f
    NSLayoutConstraint * readViewT = [NSLayoutConstraint constraintWithItem:self.redV
                                                                  attribute:NSLayoutAttributeTop
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:self.view
                                                                  attribute:NSLayoutAttributeTop
                                                                 multiplier:1.f
                                                                   constant:50.f];
    //添加约束到视图
    [self.view addConstraint:readViewW];
    [self.view addConstraint:readViewH];
    [self.view addConstraint:readViewL];
    [self.view addConstraint:readViewT];
}
2、VFL 语言
1)什么是 VFL 语言:
VFL(Visual Format Language),“可视化格式语言”。
VFL是苹果公司为了简化autolayout的编码而推出的抽象语言
2)基本语法表
功能表达式
水平方向H:
垂直方向V:
Views[view]
关系>=,==,<=
SuperView|
空间,间隙 --
优先级@value

3)具体的方法

+ (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(nullable NSDictionary<NSString *,id> *)metrics views:(NSDictionary<NSString *, id> *)views;


4)具体说一下参数

format 就是填写刚刚咱们学习的 VFL 语言,注意,这里是需要将 VFL语言写成字符串传递进去,所以这一步很容易出错,错了也不会有报错提示,需要咱们平日里多加练习与锻炼才能很好的避免一些错误

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            //没有属性
};
NSLayoutAttributeLeft/NSLayoutAttributeRight 和NSLayoutAttributeLeading/NSLayoutAttributeTrailing的区别是left/right永远是指左右,而leading/trailing在某些从右至左习惯的地区会变成,leading是右边,trailing是左边。
metrics 表示使用到的度量数组,你可以把一些VFL 语言用的值定义在一个字典里面例如创建一个字典
NSDictionary *metres = @{@"leftArglin":@20}
然后在 VFL 语言里面所用到的距离左边位置的距离,可以用leftArglin 来代替,这样的话,改想要修改距离左边的距离,就致用修改字典里面的数值,而不用每个使用到左边距离的地方都意义修改,方便大家,当然这个值可以传 nil
views:就是上面所加入到NSDictionary中的绑定的View,就是需要布局的 view 都需要写入一个字典里面来才可以.
- (void)methodTwo{
    
    //VFL(可视化格式语言)
    _blueV = [[UIView alloc]init];
    _blueV.backgroundColor = [UIColor redColor];
    [self.view addSubview:_blueV];
    
    _yellowV = [[UIView alloc]init];
    _yellowV.backgroundColor = [UIColor yellowColor];
    [self.view addSubview:_yellowV];
    
    //注意translatesAutoresizingMaskIntoConstraints 一定要设置为 NO
    self.blueV.translatesAutoresizingMaskIntoConstraints = NO;
    self.yellowV.translatesAutoresizingMaskIntoConstraints = NO;
    
    //views
    NSDictionary * views = NSDictionaryOfVariableBindings(_blueV,_yellowV);
    
    //metres
    NSDictionary * metres = @{@"readViewW":@100,@"leftArglin":@50,@"rightArglin":@50};
    
    //水平方向的约束
    NSArray * HContraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-leftArglin-[_blueV(readViewW)]-11-[_yellowV]-rightArglin-|"
                                                                    options:0
                                                                    metrics:metres
                                                                      views:views];
    //垂直方向的约束
    NSArray * VContraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[_blueV(50)]-20-[_yellowV(==_blueV)]"
                                                                    options:0
                                                                    metrics:metres
                                                                      views:views];
    
    //添加约束
    [self.view addConstraints:HContraints];
    [self.view addConstraints:VContraints];

}

5、举个例子

例子1: H:|-20-[_blueV(50)]-11-[_yellowV(50)]-20-|

分开讲解:

1)H:| -20-水平方向的布局是从屏幕的左侧20开始

2)[_blueV(50)]代表_blueV的宽度是50

3)-11-表示距离下一个控件的距离是11

4)[_yellowV(50)]代表_yellowV的宽度是50

5)-20-|表示距离屏幕右侧为20

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值