iOS 基础 - 约束布局

xib中的设置

PIN布局

上图PIN是使用最广泛最便捷的约束,它可以设置一个View的宽度和高度,父View四周的距离,或者到四周相邻其他View(如果存在)的距离,也可以选中多个View来设置,这时面板中的Equal Widths 和Equal Height 以及Align变成可设置状态。

另外在xib页面还可以拖动添加约束,按住control,点击并拖动某一个view,就会出现一条线,将这条线拖动空白部位,就可以设置点击的View与父View相关的约束,拖动到某一个兄弟View就可以设置该View与这个兄弟View相关的约束。
拖动除了在xib的界面中拖动以外,在xib的View列表中按住Control键拖动一个View到另一个View或者父View也可以添加他们之间的约束。

约束和frame

设置约束的最终还是将约束条件转换为frame来布局,因此我们要遵循一点,设置的约束要能够确定一个View的位置和大小,无论缺少那一点都会无法通过的,另外注意的是约束冲突,如果出现这种情况,我们要适当的删除某些冲突的约束,以确保系统能够确定View的frame

约束和动画

如果我们想改变约束,那么就需要我们重新设置约束,并重新布局了,约束中可改变的东西很少,constant属性就是其中一种,我们可以遍历控件上的约束,寻找到我们需要改变的约束,改变其constant值。

// 通过代码遍历找到对应的约束
NSArray *constraints = self.testView.constraints;
for (NSLayoutConstraint *constraint in constraints) {
    if (constraint.firstAttribute == NSLayoutAttributeHeight) {  // 高度
        constraint.constant = 300;
    }
}

又或者,直接在xib中寻找到改约束,control拖动到文件中,再进行设置,如下图

约束

再设置

self.contraint.constant = 200; // 设置控件顶部距离

如果想要结合动画,我们仅需调用layoutIfNeeded方法

UIView animateWithDuration:0.5 animations:^{
    [self.view setNeedsLayout];
    [self.view layoutIfNeeded];
}];

纯代码设置约束

我们需要借助 NSLayoutConstraint 类来设置约束,我们先看下某个约束的xib可视化视图

约束可视化

上图以此是约束对象、相对关系、相对对象、约束值、优先级、倍数、标识符等

接下来,我们来使用NSLayoutConstraint 来设置这些参数

NSLayoutConstraint *c1 = [NSLayoutConstraint constraintWithItem:// 约束对象
                                                      attribute:// 约束对象相关属性
                                                      relatedBy:// 相对关系
                                                         toItem:// 相对对象
                                                      attribute:// 相对对象相关属性
                                                     multiplier:// 倍数
                                                       constant:// 约束值
                          ];

如果需要使用 autolayout 布局某控件就必须设置该控件 Autoresizing 属性为NO

[testView setTranslatesAutoresizingMaskIntoConstraints:NO];
// 设置约束
NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
NSLayoutConstraint *constraint4 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:200];
NSLayoutConstraint *constraint3 = [NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:200];
// 给父视图添加该约束
[self.view addConstraints:@[constraint1,constraint2,constraint3,constraint4]];

这样,我们就设置好了测试视图的约束,该视图居中,宽高分别为200。

非常简单?试想每一个视图都真这样去做约束,简直反人类啊,有木有!

我们注意到,NSLayoutConstraint类中还有一个做约束的方法。

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

这是系统提供给开发者另一种简化约束方式VFL。

VFL约束

参数介绍

format:此参数为你的vfl语句,比如: `@“H:|-[button]-|”。

opts:枚举参数,默认写0,具体跟据你所实现的需求去选择你想要的枚举

metrics:这里是一个字典,当在format中使用了动态数据,比如:@"H:|-[button(==width)]-|",表示这个button的宽度为width,那么这个参数去哪里找呢?就是在这个字典里面找到key对就的值,如果没有找到这个值,app就会crash

views:顾名思义,这是传所有你在 vfl 中使用到的view,那在上面这句例子中的应该怎么传呢?结果是这样的:NSDictionaryOfVariableBindings(button)。如果你使用到了多个view,就可以这样 NSDictionaryOfVariableBindings(button,button1,button3...),这个名字也要跟参数format中的一一对应,缺一不可

创建完之后,我们通过调用UIView的方法。

- (void)addConstraints:(NSArray *)constraints;

将约束添加到父视图上。

NSArray *constraints1=[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[button]-|"
                            options:0
                            metrics:nil
                            views:NSDictionaryOfVariableBindings(button)];
NSArray *constraints2=[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[button(==30)]"
                            options:0
                            metrics:nil
                            views:NSDictionaryOfVariableBindings(button)];
[self.view addConstraints:constraints1];
[self.view addConstraints:constraints2];

format字符串解读

功能表达式
水平方向H:
垂直方向V:
Views[view]
SuperView
关系>=,==,<=
空间,间隙-
优先级@value

相比之前的创建约束,VFL方式要精炼很多,用起来也顺手很多。

三方框架约束

系统提供的做约束的方式有点繁琐,使用起来相当的别扭,我们不如再其基础上做层封装,简化约束代码,使用起来会更顺手;

如果不想自己封装,也可以使用三方框架,如

其中 masonry 是老牌框架,功能相对强大,完善,有着一套自己的链式语法风格。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值