代码添加约束如何实现

本文介绍了如何使用代码添加约束,包括理解纯代码设置自动布局约束的重要性,掌握`addConstraint`方法和`constraintsWithVisualFormat(VFL)`的使用。通过案例分析了添加约束的步骤、约束位置的选择以及VFL的基本语法,帮助开发者熟练掌握自动布局的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码添加约束

目标

  • 理解用纯代码设置自动布局约束的方法
  • 理解为什么在使用自动布局开发时,千万不要修改 frame?
  • 理解 VFL 语法

提示:自动布局方法的参数很多,第一次接触难免会有抵触情绪

但是参数的含义很容易懂!

为什么要学习纯代码的自动布局?

  • 自己开发第三方框架会使用

  • 其他第三方框架中会使用,遇到时能够看得懂

知识点

  • 理解用 NSLayoutConstraint 类创建具体的约束对象的步骤与参数
  • 理解用 VFL 添加自动布局的方法
  • 理解 VFL 语法

用代码实现 Autolayout的步骤

  1. 禁用 autoresizing
  2. 利用以下方法添加约束

/// 添加一个约束
- (void)addConstraint:(NSLayoutConstraint *)constraint;
/// 添加多个约束 VFL 专用
- (void)addConstraints:(NSArray *)constraints;

/// 创建一个约束
[NSLayoutConstraint constraintWithItem:...
/// 利用 VFL 创建多个约束
[NSLayoutConstraint constraintsWithVisualFormat:...

注意:约束添加的位置
  • 如果约束没有参照任何其他视图,则约束添加在自身(苹果建议),或者父视图上(常见)
  • 如果约束有参照父视图,则约束添加到父视图上

如果约束有参照兄弟视图,则约束添加到它们最近的父视图上

对于两个不同层级view之间的约束关系,添加到他们最近的共同父view上

案例 1 —— addConstraint

要求
  1. 定义一个视图 200 * 50
  2. 在任何设备上都摆放在屏幕的中心点
代码实现
  • 代码准备
- (void)viewDidLoad {
    [super viewDidLoad];

    [self autoLayout1];
}

/**
 * 案例 1
 *
 * 定义一个视图 200 * 50
 * 在任何设备上都摆放在屏幕的中心点
 */
- (void)autoLayout1 {

    UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    v.backgroundColor = [UIColor redColor];
    [self.view addSubview:v];   
}
  • 添加水平约束
// 定义约束,并且添加到 self.view 上
// 1. 水平约束
NSLayoutConstraint *horCons = [NSLayoutConstraint
                               constraintWithItem:v                 // 添加约束的视图
                               attribute:NSLayoutAttributeCenterX   // 要设置约束的属性 centerX
                               relatedBy:NSLayoutRelationEqual      // 相等
                               toItem:self.view                     // 参照的视图
                               attribute:NSLayoutAttributeCenterX   // 参照视图的属性
                               multiplier:1.0                       // 乘积
                               constant:0];                         // 约束值,如果和参照属性想等,此处传入 0
// 将水平约束添加到视图的父视图上
[self.view addConstraint:horCons];
  • 添加垂直约束,由于一般约束设置完成后,直接添加给 view,所以不会定义临时变量
// 2. 垂直约束
[self.view addConstraint:[NSLayoutConstraint
                          constraintWithItem:v
                          attribute:NSLayoutAttributeCenterY
                          relatedBy:NSLayoutRelationEqual
                          toItem:self.view
                          attribute:NSLayoutAttributeCenterY
                          multiplier:1.0
                          constant:0]];

运行测试,会报以下错误

    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
    ...

在使用代码开始时,默认是使用 AutoResizing

而 AutoResizing 和 AutoLayout 不能共存

因此用代码开发的时候,一定要把视图的 translatesAutoresizingMaskIntoConstraints 设置为 NO

  • 取消 autoresizing
// 0. 取消 autoresizing
v.translatesAutoresizingMaskIntoConstraints = NO;

运行测试,视图不见了,因为只要使用自动布局,frame 的计算工作会被自动布局系统完全接管

提示:在使用自动布局开发时,千万不要修改 frame

  • 添加宽度约束
// 3. 设置宽度
[self.view addConstraint:[NSLayoutConstraint
                              constraintWithItem:v                      // 添加约束的视图
                              attribute:NSLayoutAttributeWidth          // 宽度
                              relatedBy:NSLayoutRelationEqual           // 想等
                              toItem:nil                                // 没有参照视图,传入 nil
                              attribute:NSLayoutAttributeNotAnAttribute // 当 toItem == nil 时,传入 NSLayoutAttributeNotAnAttribute
                              multiplier:1.0                            // 乘积
                              constant:200]];                           // 约束值,如果没有参照对象,直接传入宽度数值
  • 添加高度约束
// 4. 设置高度
[self.view addConstraint:[NSLayoutConstraint
                          constraintWithItem:v
                          attribute:NSLayoutAttributeHeight
                          relatedBy:NSLayoutRelationEqual
                          toItem:nil
                          attribute:NSLayoutAttributeNotAnAttribute
                          multiplier:1.0
                          constant:50]];

VFL 介绍

  • 为了简化程序员开发时编写大量的约束,苹果推出了 VFL —— 可视化格式语言
  • VFL 语法

    • H: 水平方向
    • V: 垂直方向
    • | 边界
    • [视图名称]
    • (常数值)
    • = >= <= 关系
    • - 距离
  • VFL 示例

H:|-0-[button]-0-|
  • 按钮 距离 左右 两边为 0
V:|-0-[button]-0-|
  • 按钮 距离 上下 两边为 0
H:|-20-[button(50)]
  • 按钮 距离 边 20
  • 按钮宽度 50
V:[button(40)]-20-|
  • 按钮 距离 边 20
  • 按钮高度 40

VFL 没有提供居中对齐的方式

案例 2 —— constraintsWithVisualFormat(VFL)

要求
  1. 定义两个 UITextField 水平距离左右两边 20 点
  2. 第一个 UITextField 垂直距离顶边 20 点
  3. 第二个 UITextField 垂直距离第一个 20 点

  4. 代码准备

- (void)viewDidLoad {
    [super viewDidLoad];

    [self autoLayout2];
}

/**
 * 案例 2
 *
 * 定义两个 UITextField 水平距离左右两边 20 点
 * 第一个 UITextField 垂直距离顶边 20 点
 * 第二个 UITextField 垂直距离第一个 20 点
 */
- (void)autoLayout2 {

    // 1. 创建控件
    UITextField *tf1 = [[UITextField alloc] initWithFrame:CGRectMake(20, 20, 200, 40)];
    tf1.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:tf1];

    UITextField *tf2 = [[UITextField alloc] initWithFrame:CGRectMake(20, 80, 200, 40)];
    tf2.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:tf2];
}
  • 取消 autoresizing
// 2. 取消 autoresizing
for (UIView *v in self.view.subviews) {
    v.translatesAutoresizingMaskIntoConstraints = NO;
}

一旦取消了 autoresizing,控件的 frame 就会失效

  • 添加 第一个文本框的宽度 约束
// 3. 添加约束
// 3.0 生成控件映射字典,视图影射字典,告诉系统 VFL 中的 [控件] 对应哪个控件
NSDictionary *viewDict = @{@"tf1": tf1, @"tf2": tf2};

[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:|-20-[tf1]-20-|" // VFL
                           options:0                                        // 通常传入 0
                           metrics:nil                                      // 通常传入 nil
                           views:viewDict]];                                // 视图影射字典,告诉系统 VFL 中的 [控件] 对应哪个控件
  • 添加 第二个文本框的宽度 约束
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:|-20-[tf2]-20-|" // VFL
                           options:0                                        // 通常传入 0
                           metrics:nil                                      // 通常传入 nil
                           views:viewDict]];                                // 视图影射字典,告诉系统 VFL 中的 [控件] 对应哪个控件
  • 添加高度约束
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:|-20-[tf1(28)]-20-[tf2(==tf1)]" // VFL
                           options:0                                        // 通常传入 0
                           metrics:nil                                      // 通常传入 nil
                           views:viewDict]];                                // 视图影射字典,告诉系统 VFL 中的 [控件] 对应哪个控件
  • metrics 字典使用
// 设置 VFL 中的数值字典
    NSDictionary *metrics = @{@"space": @(100)};
    [self.view addConstraints:[NSLayoutConstraint
                               constraintsWithVisualFormat:@"V:|-20-[tf1(28)]-(==space)-[tf2(==tf1)]" // VFL
                               options:0                                        // 通常传入 0
                               metrics:metrics                                  // 设置 VFL 中的数值字典
                               views:viewDict]];                                // 视图影射字典,告诉系统 VFL 中的 [控件] 对应哪个控件

VFL 文档地址

  • iOS -> Cocoa Touch Layer -> UIKit -> Guide -> AutoLayoutGuid
  • Part V: Appendix Visual Format Language


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值