深入理解 iOS 中的 AutoLayout(二)

目录

前言

一、UIStackView自动布局

1.简单的UIStackView

2.嵌套的UIStackView

二、AutoLayout高级用法

1.以编程方式创建约束

1.布局锚点

1.主要特点

2.常见子类

1.NSLayoutXAxisAnchor

2.NSLayoutYAxisAnchor

3.NSLayoutDimension       

3.常用方法        

4.示例代码

1.将两个视图垂直对齐

2.将视图居中放置

3.设置固定间距

4.设置相对宽度

5.设置视图边距(内边距)

2.NSLayoutConstraint类

1.基本概念

2.常用方法

1.创建约束

2.激活和停用约束

3.自动布局和约束的优先级

3.NSLayoutConstraint 示例

3.VFL语言

1.基本概念

1.水平和垂直布局

2.视图名称

3.边距和间距

4.固定宽度和高度

5.优先级

6.视图间关系

2.基本语法

3.VFL示例

                    

        


前言

     通过上一篇文章,我们了解了AutoLayout的一些基本概念,这篇文章我们将通过一个具体的例子看看AutoLayout的用法。

一、UIStackView自动布局

1.简单的UIStackView

        我们通过下面的示例,看看如何使用Auto Layout实现一个简单的UIStackView。       

图1. 简单的UIStackView布局

        我们首先看一下这个UI的布局,一个UIStackView嵌套三个控件,分辨是用来显示文本的UILabe,一个UIImageView用来显示花朵,一个编辑按钮。

        这里我们首先拖拽一个纵向的UIStackView。

图2.查找纵向的UIStackView

        然后按住control键,当箭头指向父视图的时候,我们松开control键,然后设置UIStackView的约束。

        图3.设置UIStackView距离父视图的间距

        图4.UIStackView间距

        然后我们设置UIStackView的属性。

        图5.UIStackView属性设置

        UIStackView属性设置完成之后,我们一次把UILabel,UIImageView,UIButton拖拽到UIStackView中,然后设置下UILabel居中显示,设置下UIImageView的属性,之后,一个简单的UIStackView布局就完成了。

        UIImageView的属性设置如下:

图5.UIImageView属性设置

图6.UIImageView属性设置

2.嵌套的UIStackView

        上面通过一个简单的UIStackView示例介绍了Auto Layout的用法。接下来我们通过一个嵌套的稍微复杂的例子,看看UIStackView的实现。

图7.UIStackView嵌套       

        我们分析下这个UI中的UIStackView的元素,结构如下入所示,有兴趣的可以自己实现一下。

        图8.UIStackView的嵌套布局

         这里不一一赘述了,源代码在这里

二、AutoLayout高级用法

1.以编程方式创建约束

1.布局锚点

        Layout Anchors(布局锚点)类NSLayoutAnchor 是 iOS 和 macOS 开发中用于自动布局(Auto Layout)的核心类之一。它简化了使用代码创建布局约束的过程。通过 NSLayoutAnchor,你可以为视图设置更加直观的布局规则,而无需使用传统的 NSLayoutConstraint 的方法。

1.主要特点

        NSLayoutAnchor 是抽象类,不能直接实例化。它有三个子类:NSLayoutXAxisAnchor、NSLayoutYAxisAnchor 和 NSLayoutDimension,分别用于设置 X 轴、Y 轴和尺寸的约束。

        通过 NSLayoutAnchor 可以轻松地创建视图之间的关系,如对齐、中心对齐、等宽等高等约束。

2.常见子类
1.NSLayoutXAxisAnchor

        管理 X 轴上的约束,通常是 leadingAnchor、trailingAnchor、leftAnchor、rightAnchor 和 centerXAnchor。

2.NSLayoutYAxisAnchor

        管理 Y 轴上的约束,通常是 topAnchor、bottomAnchor 和 centerYAnchor。

3.NSLayoutDimension       

        处理视图的宽度和高度约束。通常是 widthAnchor 和 heightAnchor。

3.常用方法        

• constraint(equalTo:):设置两个锚点相等的约束。

• constraint(greaterThanOrEqualTo:):设置第一个锚点不小于第二个锚点的约束。

• constraint(lessThanOrEqualTo:):设置第一个锚点不大于第二个锚点的约束。

• constraint(equalTo:constant:):设置两个锚点相等的约束,并添加一个偏移量。

• constraint(greaterThanOrEqualTo:constant:) 和 constraint(lessThanOrEqualTo:constant:):同样适用于设置带偏移量的约束。

4.示例代码
1.将两个视图垂直对齐

        例如我们要实现下面的效果图:

图9.两个视图垂直对齐

        我们可以通过下面的代码来实现:

- (void)setupDemo1 {
    // 创建视图
    UIView *view1 = [[UIView alloc] init];
    UIView *view2 = [[UIView alloc] init];
    
    view1.backgroundColor = [UIColor redColor];
    view2.backgroundColor = [UIColor blueColor];
    
    view1.translatesAutoresizingMaskIntoConstraints = NO;
    view2.translatesAutoresizingMaskIntoConstraints = NO;
    
    // 将视图添加到父视图中
    [self.view addSubview:view1];
    [self.view addSubview:view2];
    
    // 设置 view1 的宽度和高度
    [view1.widthAnchor constraintEqualToConstant:100].active = YES;
    [view1.heightAnchor constraintEqualToConstant:100].active = YES;
    
    // 设置 view2 的宽度和高度
    [view2.widthAnchor constraintEqualToConstant:100].active = YES;
    [view2.heightAnchor constraintEqualToConstant:150].active = YES;
    
    // 将 view1 的顶部与父视图的安全区域顶部对齐,并居中显示
    [view1.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:100].active = YES;
    [view1.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor].active = YES;
    
    // 将 view2 放置在 view1 的下方,并保持垂直间距为 20
    [view2.topAnchor constraintEqualToAnchor:view1.bottomAnchor constant:20].active = YES;
    [view2.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor].active = YES;
}
2.将视图居中放置

        我们可以通过下面的代码将视图居中放置:

- (void)setupDemo2 {
    UIView *containerView = [[UIView alloc] init];
    UIView *childView = [[UIView alloc] init];
    
    containerView.backgroundColor = [UIColor lightGrayColor];
    childView.backgroundColor = [UIColor greenColor];
    
    containerView.translatesAutoresizingMaskIntoConstraints = NO;
    childView.translatesAutoresizingMaskIntoConstraints = NO;
    
    [self.view addSubview:containerView];
    [containerView addSubview:childView];
    
    // 设置 containerView 的约束,充满整个屏幕
    [containerView.topAnchor constraintEqualToAnchor:self.view.topAnchor].active = YES;
    [containerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor].active = YES;
    [containerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = YES;
    [containerView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES;
    
    // 将 childView 水平居中于 containerView
    [childView.centerXAnchor constraintEqualToAnchor:containerView.centerXAnchor].active = YES;
    
    // 将 childView 垂直居中于 containerView
    [childView.centerYAnchor constraintEqualToAnchor:containerView.centerYAnchor].active = YES;
    
    // 设置 childView 的宽度为 200
    [childView.widthAnchor constraintEqualToConstant:200].active = YES;
    
    // 设置 childView 的高度为 200
    [childView.heightAnchor constraintEqualToConstant:200].active = YES;
}
3.设置固定间距

        我们可以通过下面的代码,设置视图的间距:

- (void)setupDemo3 {
    UIView *view1 = [[UIView alloc] init];
    UIView *view2 = [[UIView alloc] init];
    
    view1.backgroundColor = [UIColor purpleColor];
    view2.backgroundColor = [UIColor orangeColor];
    
    view1.translatesAutoresizingMaskIntoConstraints = NO;
    view2.translatesAutoresizingMaskIntoConstraints = NO;
    
    [self.view addSubview:view1];
    [self.view addSubview:view2];
    
    // 将 view1 放置在屏幕顶部
    [view1.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:100].active = YES;
    [view1.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:20].active = YES;
    
    // 将 view1 的宽度和高度设置为 100
    [view1.widthAnchor constraintEqualToConstant:100].active = YES;
    [view1.heightAnchor constraintEqualToConstant:100].active = YES;
    
    // 设置 view2 和 view1 之间的垂直间距为 20
    [view2.topAnchor constraintEqualToAnchor:view1.bottomAnchor constant:20].active = YES;
    [view2.leadingAnchor constraintEqualToAnchor:view1.leadingAnchor].active = YES;
    
    // 将 view2 的宽度和高度设置为 100
    [view2.widthAnchor constraintEqualToConstant:100].active = YES;
    [view2.heightAnchor constraintEqualToConstant:100].active = YES;
}
4.设置相对宽度

        我们可以通过下面的代码设置相对宽度

- (void)setupDemo4 {
    UIView *containerView = [[UIView alloc] init];
    UIView *view1 = [[UIView alloc] init];
    UIView *view2 = [[UIView alloc] init];
    
    containerView.backgroundColor = [UIColor lightGrayColor];
    view1.backgroundColor = [UIColor redColor];
    view2.backgroundColor = [UIColor blueColor];
    
    containerView.translatesAutoresizingMaskIntoConstraints = NO;
    view1.translatesAutoresizingMaskIntoConstraints = NO;
    view2.translatesAutoresizingMaskIntoConstraints = NO;
    
    [self.view addSubview:containerView];
    [containerView addSubview:view1];
    [containerView addSubview:view2];
    
    // 设置 containerView 的约束,充满整个屏幕
    [containerView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor].active = YES;
    [containerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor].active = YES;
    [containerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = YES;
    [containerView.heightAnchor constraintEqualToConstant:200].active = YES;
    
    // 设置 view1 的宽度是 containerView 的一半
    [view1.widthAnchor constraintEqualToAnchor:containerView.widthAnchor multiplier:0.5].active = YES;
    
    // 设置 view2 的宽度和 view1 相同
    [view2.widthAnchor constraintEqualToAnchor:view1.widthAnchor].active = YES;
    
    // 将 view1 和 view2 水平并排放置
    [view1.leadingAnchor constraintEqualToAnchor:containerView.leadingAnchor constant:10].active = YES;
    [view2.leadingAnchor constraintEqualToAnchor:view1.trailingAnchor constant:10].active = YES;
    
    // 设置 view1 和 view2 的高度相同
    [view1.heightAnchor constraintEqualToAnchor:containerView.heightAnchor constant:-20].active = YES;
    [view2.heightAnchor constraintEqualToAnchor:view1.heightAnchor].active = YES;
}
5.设置视图边距(内边距)

        通过下面的代码,我们可以设置内边距。

- (void)setupDemo5 {
    UIView *containerView = [[UIView alloc] init];
    UIView *childView = [[UIView alloc] init];
    
    containerView.backgroundColor = [UIColor lightGrayColor];
    childView.backgroundColor = [UIColor yellowColor];
    
    containerView.translatesAutoresizingMaskIntoConstraints = NO;
    childView.translatesAutoresizingMaskIntoConstraints = NO;
    
    [self.view addSubview:containerView];
    [containerView addSubview:childView];
    
    // 设置 containerView 的约束,充满整个屏幕
    [containerView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor].active = YES;
    [containerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor].active = YES;
    [containerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = YES;
    [containerView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES;
    
    // 设置 childView 与 containerView 的上下左右各保持 10 的距离
    [childView.topAnchor constraintEqualToAnchor:containerView.topAnchor constant:10].active = YES;
    [childView.leadingAnchor constraintEqualToAnchor:containerView.leadingAnchor constant:10].active = YES;
    [childView.trailingAnchor constraintEqualToAnchor:containerView.trailingAnchor constant:-10].active = YES;
    [childView.bottomAnchor constraintEqualToAnchor:containerView.bottomAnchor constant:-10].active = YES;
}

2.NSLayoutConstraint类

        通过 NSLayoutConstraint,你可以为视图设置布局约束,以确定视图在屏幕上的大小和位置。NSLayoutConstraint 允许你定义视图之间的关系,比如视图的宽度、高度、对齐方式以及它们之间的间距。  

1.基本概念

        这个类其实在上篇文章里面有介绍,这里不做介绍了,这篇文章主要看一下这个类的用法。  

2.常用方法

1.创建约束

        通过类方法 constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant: 来创建自定义约束。

NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:view1
                                                              attribute:NSLayoutAttributeWidth
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:view2
                                                              attribute:NSLayoutAttributeWidth
                                                             multiplier:1.0
                                                               constant:0];

2.激活和停用约束

        可以通过 setActive: 或者 activateConstraints: 方法来激活约束。激活意味着该约束在布局系统中生效。

constraint.active = YES;
// 或者激活多个约束
[NSLayoutConstraint activateConstraints:@[constraint1, constraint2]];

3.自动布局和约束的优先级

        通过priority属性设置约束的优先级。

constraint.priority = UILayoutPriorityDefaultHigh; // 优先级为 750

3.NSLayoutConstraint 示例

        以下是一个使用 NSLayoutConstraint 创建简单布局的示例。在这个示例中,我们将一个 UIView 居中并设置固定的宽度和高度。

- (void)setupLayoutConstraints {
    UIView *childView = [[UIView alloc] init];
    childView.backgroundColor = [UIColor blueColor];
    childView.translatesAutoresizingMaskIntoConstraints = NO;
    
    [self.view addSubview:childView];
    
    // 中心X约束
    NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:childView
                                                                         attribute:NSLayoutAttributeCenterX
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:self.view
                                                                         attribute:NSLayoutAttributeCenterX
                                                                        multiplier:1.0
                                                                          constant:0];
    
    // 中心Y约束
    NSLayoutConstraint *centerYConstraint = [NSLayoutConstraint constraintWithItem:childView
                                                                         attribute:NSLayoutAttributeCenterY
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:self.view
                                                                         attribute:NSLayoutAttributeCenterY
                                                                        multiplier:1.0
                                                                          constant:0];
    
    // 宽度约束
    NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:childView
                                                                       attribute:NSLayoutAttributeWidth
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:nil
                                                                       attribute:NSLayoutAttributeNotAnAttribute
                                                                      multiplier:1.0
                                                                        constant:200];
    
    // 高度约束
    NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:childView
                                                                        attribute:NSLayoutAttributeHeight
                                                                        relatedBy:NSLayoutRelationEqual
                                                                           toItem:nil
                                                                        attribute:NSLayoutAttributeNotAnAttribute
                                                                       multiplier:1.0
                                                                         constant:200];
    
    // 激活约束
    [NSLayoutConstraint activateConstraints:@[centerXConstraint, centerYConstraint, widthConstraint, heightConstraint]];
}

3.VFL语言

        通过 VFL,你可以快速创建一系列约束,这些约束描述了视图之间的关系,如对齐、大小、间距等。

1.基本概念

1.水平和垂直布局

        你可以定义水平 (H:) 或垂直 (V:) 布局约束。

        例如:H:|[view1][view2]| 表示 view1 和 view2 在水平方向上排列在一起。

2.视图名称

        视图在 VFL 中使用中括号 [] 包围,例如 [view1]。

        视图名称对应的是你代码中声明的实际视图。

3.边距和间距

        你可以在视图之间添加固定的间距或边距,例如 H:|-10-[view1]-10-[view2]-10-|,表示 view1 和 view2 之间有 10 点的间距,两侧各有 10 点的边距。

4.固定宽度和高度

        你可以为视图设置固定宽度和高度,例如 H:[view1(100)] 表示 view1 的宽度为 100 点。

5.优先级

        你可以为约束设置优先级,通过在 @ 符号后添加优先级值来实现,例如 H:[view1(>=100@750)] 表示 view1 的宽度至少为 100 点,优先级为 750。

6.视图间关系

        你可以定义视图之间的相对关系,例如 H:[view1(==view2)] 表示 view1 的宽度等于 view2 的宽度。                

2.基本语法

  1. 水平布局:H: 表示水平布局。
  2. 垂直布局:V: 表示垂直布局。
  3. 边距:用 | 表示父视图的边缘。
  4. 间距:在视图之间添加间距,可以用数字或系统默认值 -。
  5. 视图大小:用括号 () 指定视图的宽度或高度。
  6. 优先级:在 @ 后面添加优先级值。

3.VFL示例

       以下是一些使用 VFL 创建布局的示例:

        示例1:水平排列两个视图,之间有固定的间距。

NSDictionary *views = @{@"view1": view1, @"view2": view2};

// 水平布局 view1 和 view2,之间间距为 10 点,view1 和 view2 紧贴父视图的左右边缘
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[view1]-10-[view2]-10-|"
                                                               options:0
                                                               metrics:nil
                                                                 views:views];
[NSLayoutConstraint activateConstraints:constraints];

        示例2:垂直排列两个视图,设置固定高度。

NSDictionary *views = @{@"view1": view1, @"view2": view2};

// 垂直布局 view1 和 view2,view1 的高度为 50 点,view2 的高度为 100 点
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[view1(50)]-20-[view2(100)]"
                                                               options:0
                                                               metrics:nil
                                                                 views:views];
[NSLayoutConstraint activateConstraints:constraints];

                    

        

        

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫柱子哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值