通过代码添加约束之NSLayoutConstraint

标签: ios 可视化 约束
317人阅读 评论(0) 收藏 举报

什么是NSLayoutConstraint?

在xib中,我们可以用拖拽约束的方式来给空间添加约束条件,但是如果控件过多,则整个xib文件中的线条会变得混乱不堪,虽然苹果在极力推荐可视化的加约束方式,但是还是给我们提供了代码的方式来添加约束:NSLayoutConstraint。

如何使用NSLayoutConstraint?

在使用NSLayoutConstraint前,我们需要知道一个小的知识点:Autoresizing Mask。在使用 Auto Layout 时,首先需要将视图的 setTranslatesAutoresizingMaskIntoConstraints属性设置为 NO。这个属性默认为 YES。当它为 YES 时,运行时系统会自动将 Autoresizing Mask 转换为 Auto Layout 的约束,这些约束很有可能会和我们自己添加的产生冲突。 我们常常会忘了做这一步,然后引起的约束报错就是这样的:


没有关闭setTranslatesAutoresizingMaskIntoConstraints属性报的问题

在xib中,如果我们勾选了use auto layout,则编译器会自动帮我们关闭Autoresizing Mask,如果是使用代码添加约束,则需要手动关闭Autoresizing Mask。

setTranslatesAutoresizingMaskIntoConstraints这个方法是交给被添加约束的视图来执行的,关闭该视图的Autoresizing Mask。在添加约束前,就应该关闭该属性。

使用NSLayoutConstraint为视图添加约束

Auto Layout 中约束对应的类为 NSLayoutConstraint,一个 NSLayoutConstraint 实例代表一条约束。

NSLayoutConstraint有两个方法,我们主要介绍 constraintWithItem:也是最常用的:

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

该方法有7个参数,不过不用但心,这七个参数的联系是很紧密的,前三个和被约束的视图有关,后四个和他的父视图有关。这个方法连起来可以翻译如下:view1的某个属性(attr1)等于view2的某个属性(attr2)的值的多少倍(multiplier)加上某个常量(constant)。描述的是一个view与另外一个view的位置和大小约束关系。其中属性attribute有上、下、左、右、宽、高等,关系relation有小于等于、等于、大于等于。需要注意的是,小于等于 或 大于等于 优先会使用 等于 关系,如果 等于 不能满足,才会使用 小于 或 大于。例如设置一个 大于等于100 的关系,默认会是 100,当视图被拉伸时,100 无法被满足,尺寸才会变得更大。

下边我们上代码,看看如何使用这个类来给视图添加约束。

假如我们设计一个简单的页面。一个子view在父view中,其中子view的上下左右边缘都离父view的边缘40个像素。这个我们该如何写呢?如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.view.backgroundColor = [UIColor yellowColor];


    UIView *subView = [[UIView alloc] init];
    subView.backgroundColor = [UIColor redColor];
    // 在设置约束前,先将子视图添加进来
    [self.view addSubview:subView];

    // 使用autoLayout约束,禁止将AutoresizingMask转换为约束
    [subView setTranslatesAutoresizingMaskIntoConstraints:NO];

    // 设置subView相对于VIEW的上左下右各40像素
    NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:40];
    NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:40];
    // 由于iOS坐标系的原点在左上角,所以设置右边距使用负值
    NSLayoutConstraint *constraint3 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-40];

    // 由于iOS坐标系的原点在左上角,所以设置下边距使用负值
    NSLayoutConstraint *constraint4 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-40];

    // 将四条约束加进数组中
    NSArray *array = [NSArray arrayWithObjects:constraint1, constraint2, constraint3, constraint4 ,nil];
    // 把约束条件设置到父视图的Contraints中
    [self.view addConstraints:array];
}

然后我们看运行效果:


添加约束后的效果

这里有几个注意点

  1. 添加约束前确定已经把需要布局的子view添加到父view上了
  2. 一定要禁止将Autoresizing Mask转换为约束
  3. 要把子view的约束加在父view上
  4. 因为iOS中原点在左上角所以使用offset时注意right和bottom用负数

我们再添加一个需求:
子view在父view的中间,且子view长200,高100。

    // ssubView在subView中间,宽高200,100
    UIView *ssubView = [[UIView alloc] init];
    ssubView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:ssubView];
    [ssubView setTranslatesAutoresizingMaskIntoConstraints:NO];

    // 加约束
    NSLayoutConstraint *sContraint1 = [NSLayoutConstraint constraintWithItem:ssubView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0];
    NSLayoutConstraint *sContraint2 = [NSLayoutConstraint constraintWithItem:ssubView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0];
    NSLayoutConstraint *sConstraint3 = [NSLayoutConstraint constraintWithItem:ssubView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:300];
    NSLayoutConstraint *sConstraint4 = [NSLayoutConstraint constraintWithItem:ssubView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:200];

    NSArray *array2 = [NSArray arrayWithObjects:sContraint1, sContraint2,sConstraint3,sConstraint4, nil];
    [self.view addConstraints: array2];

查看运行效果:


添加新需求后的效果

这里有几个注意点

  1. 如果是设置view自身的属性,不涉及到与其他view的位置约束关系。比如view自身的宽、高等约束时,方法constraintWithItem:的第四个参数view2(secondItem)应设为nil;且第五个参数attire(secondAttribute)应设为NSLayoutAttributeNotAnAttribute 。
  2. 在设置宽和高这两个约束时,relatedBy参数使用的是 NSLayoutRelationGreaterThanOrEqual,而不是 NSLayoutRelationEqual。因为 Auto Layout 是相对布局,所以通常你不应该直接设置宽度和高度这种固定不变的值,除非你很确定视图的宽度或高度需要保持不变。
查看评论

组合查询

用PB进行数据库应用系统开发时,我们经常要对大量的数据进行筛选、查询,得到符合要求的记录,这就需要用到组合条件查询功能。我在作应用系统开发时,就自己编写了一个简单而又实用的组合条件查询模板窗口,只要用...
  • xingjiaren
  • xingjiaren
  • 2001-04-10 14:22:00
  • 739

Swift代码动态创建NSLayoutConstraint布局

示例效果 说明 黄色lable为子view(childView),红色view为父view(parentView)。两者关系为: childView在距离父控件的左右各20边距处, 高度25。c...
  • heyufei
  • heyufei
  • 2016-12-17 18:38:24
  • 851

iOS --- 在代码中使用NSLayoutConstraint添加AutoLayout的约束条件

AutoLayout是iOS开发中的布局适配神器。常在storyboard和xib文件中直接使用, 用于不同屏幕大小的适配。而在某些情况下,需要使用代码实现AutoLayout,则可以使用NSLayo...
  • icetime17
  • icetime17
  • 2015-09-13 20:12:52
  • 2541

代码中添加约束(NSLayoutConstraint)

方式一介绍 代码约束是通过NSLayoutConstraint类进行约束的, 第一种方式就是通过其类方法constraintWithItem: attribute: relatedBy: toIte...
  • st646889325
  • st646889325
  • 2016-12-07 09:14:54
  • 302

Swift开发:NSLayoutConstraint纯代码实现自动布局-初级篇

要求 宽高200的view,通过代码,使得view在距离父控件的右下角20边距处 /* 约束的设置,控件内部约束由自己添加,比如宽高,如果是与其他的            控件约束那么有父控件...
  • taoerit
  • taoerit
  • 2016-05-04 18:35:11
  • 7602

iOS 10 Auto Layout界面自动布局系列3-使用原生NSLayoutConstraint添加布局约束

本系列的第一篇文章介绍了自动布局的基本原理,第二篇文章通过一个简单的例子演示了如何使用Xcode的Interface Builder(简称IB)以可视化方式添加约束。本篇为该系列的第三篇文章,主要介绍...
  • pucker
  • pucker
  • 2015-04-16 16:05:15
  • 34146

Swift NSLayoutConstraint 加约束Constraint

//与父视图的左右间距10//NSLayoutFormatDirectionLeadingToTrailing //水平方向上goodPicImage距离父控件左边10个像素距离,距离右边10个...
  • kaplaSxiao
  • kaplaSxiao
  • 2016-05-11 18:17:12
  • 2776

IOS开发通过代码方式使用AutoLayout (NSLayoutConstraint + Masonry)

随着iPhone6+设备的上市,如何让手头上的APP适配iPhone4/4s,iPhone5/5s,iPhone6/6s,iPhone 6p/6ps多种机型多种屏幕尺寸变得尤为迫切和必要。...
  • He_jiabin
  • He_jiabin
  • 2015-10-19 17:35:02
  • 4303

UITableViewCell使用Autolayout布局的解决过程

大屏iPhone的发布,感觉是时候必须使用autolayout布局的,最近看了很多的文章,开始尝试使用autolayout布局.UITableView是项目中最常用的控件,所以我决定从使用autola...
  • a732264588
  • a732264588
  • 2014-12-16 14:03:16
  • 2454

通过代码 新增 和 “修改”NSLayoutConstraint

今天因为要弄一个瀑布流里面item的动态加载, 所以考虑把里面的一些空间的高度设成0从而实现“隐藏”效果 网上对这类修改是 关联 NSLayoutConstraint 然后设置对应的consta...
  • sd19871122
  • sd19871122
  • 2016-01-26 23:52:02
  • 3936
    个人资料
    持之以恒
    等级:
    访问量: 21万+
    积分: 3975
    排名: 9890
    联系方式
    欢迎联系颜华
    扫码添加微信
    博客专栏