前言

说到iOS自动布局,有很多的解决办法。有的人使用xib/storyboard自动布局,也有人使用frame来适配。对于前者,笔者并不喜欢,也不支持。对于后者,更是麻烦,到处计算高度、宽度等,千万大量代码的冗余,对维护和开发的效率都很低。

笔者在这里介绍纯代码自动布局的第三方库:Masonry。这个库使用率相当高,在全世界都有大量的开发者在使用,其star数量也是相当高的。

效果图

本节详解Masonry的以动画的形式更新约束的基本用法,先看看效果图:

我们这里初始按钮是一个很小的按钮,点击就不断放大,最大就放大到全屏幕。

核心代码

看下代码:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 
@interface UpdateConstraintsController ()
 
@property (nonatomic, strong) UIButton *growingButton;
@property (nonatomic, assign) CGFloat scacle;
 
@end
 
@implementation UpdateConstraintsController
 
- (void)viewDidLoad {
  [super viewDidLoad];
  
  self.growingButton = [UIButton buttonWithType:UIButtonTypeSystem];
  [self.growingButton setTitle:@"点我放大" forState:UIControlStateNormal];
  self.growingButton.layer.borderColor = UIColor.greenColor.CGColor;
  self.growingButton.layer.borderWidth = 3;
  
  [self.growingButton addTarget:self action:@selector(onGrowButtonTaped:) forControlEvents:UIControlEventTouchUpInside];
  [self.view addSubview:self.growingButton];
  self.scacle = 1.0;
  
  [self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {
    make.center.mas_equalTo(self.view);
    
    // 初始宽、高为100,优先级最低
    make.width.height.mas_equalTo(100 * self.scacle).priorityLow();
    // 最大放大到整个view
    make.width.height.lessThanOrEqualTo(self.view);
  }];
}
 
#pragma mark - updateViewConstraints
- (void)updateViewConstraints {
[self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {
   make.center.mas_equalTo(self.view);
  
   // 初始宽、高为100,优先级最低
   make.width.height.mas_equalTo(100 * self.scacle).priorityLow();
   // 最大放大到整个view
   make.width.height.lessThanOrEqualTo(self.view);
}];
  
  [super updateViewConstraints];
}
 
- (void)onGrowButtonTaped:(UIButton *)sender {
  self.scacle += 0.5;
  
  // 告诉self.view约束需要更新
  [self.view setNeedsUpdateConstraints];
  // 调用此方法告诉self.view检测是否需要更新约束,若需要则更新,下面添加动画效果才起作用
  [self.view updateConstraintsIfNeeded];
  
  [UIView animateWithDuration:0.3 animations:^{
    [self.view layoutIfNeeded];
  }];
}
 
@end
 

讲解

更新约束的方法是:mas_updateConstraints。下面笔者一行行代码说明。

让控件始终居中显示:

 
1
2
3
 
make.center.mas_equalTo(self.view);
 

让控件的宽和高相等且设置其优先级最低。关于优先级,这里先不细讲,后续文章会专门讲解。

 
1
2
3
 
make.width.height.mas_equalTo(100 * self.scacle).priorityLow();
 

让控件的宽和高小于或者等于self.view的宽和高,因此这个控件的最多能放大到全屏幕。

 
1
2
3
 
make.width.height.lessThanOrEqualTo(self.view);
 

将这三行代码放在一起,形成的话就是:使控件与父视图始终保持居中,控件的宽和高最大不能超过屏幕,且控件的宽和高可以变化。由于我们设置了第二行的代码优先级为priorityLow,因此其优先级是最低的,所以就可以保证宽高不能超过屏幕。

其实,当我们将更新代码放到updateViewConstraints这个方法中时,我们在viewDidLoad方法中写的:

 
1
2
3
4
5
6
7
8
9
10
 
  [self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {
    make.center.mas_equalTo(self.view);
    
    // 初始宽、高为100,优先级最低
    make.width.height.mas_equalTo(100 * self.scacle).priorityLow();
    // 最大放大到整个view
    make.width.height.lessThanOrEqualTo(self.view);
  }];
 

就不需要了。这里写上去的目的只是想说明用与不用都没有关系。

想要更新约束时添加动画,就需要调用关键的一行代码:setNeedsUpdateConstraints,这是选择对应的视图中的约束需要更新。

对于updateConstraintsIfNeeded这个方法并不是必须的,但是有时候不调用就无法起到我们的效果。但是,官方都是这么写的,从约束的更新原理上讲,这应该写上。我们要使约束立即生效,就必须调用layoutIfNeeded此方法。看下面的方法,就是动画更新约束的核心代码:

 
1
2
3
4
5
6
7
8
9
10
 
// 告诉self.view约束需要更新
[self.view setNeedsUpdateConstraints];
// 调用此方法告诉self.view检测是否需要更新约束,若需要则更新,下面添加动画效果才起作用
[self.view updateConstraintsIfNeeded];
 
[UIView animateWithDuration:0.3 animations:^{
  [self.view layoutIfNeeded];
}];
 

Masonry 动画更新约束的更多相关文章

  1. Masonry整体动画更新约束

    前言 说到iOS自动布局,有很多的解决办法.有的人使用xib/storyboard自动布局,也有人使用frame来适配.对于前者,笔者并不喜欢,也不支持.对于后者,更是麻烦,到处计算高度.宽度等,千万 ...

  2. Masonry remake更新约束

    前言 说到iOS自动布局,有很多的解决办法.有的人使用xib/storyboard自动布局,也有人使用frame来适配.对于前者,笔者并不喜欢,也不支持.对于后者,更是麻烦,到处计算高度.宽度等,千万 ...

  3. Xcode8更新约束

    Xcode升级之后就会发现约束设置好,想更新一下约束,看看约束是不是刚刚好,习惯性的去点右下角的更新约束的结果却发现没有更新约束的这一项了,好尴尬. 后来发现原来在Xcode8的约束更新换了一个地方, ...

  4. Masonry控制台打印约束冲突问题解决

    不知道你是不是视图的布局也是用的第三方Masonry,在使用中是不是也遇到了控制台约束冲突的警告打印,看下图: 从输出的信息可以知道,有的控件的约束明显重复了设置,所以指出了是哪个控件,重复设置了哪些 ...

  5. snapkit更新约束崩溃的问题

    最近在使用snapkit布局时,竟然发现更新约束会导致崩溃,为什么这样呢? checkButton.snp.makeConstraints { (make) in make.left.top.equa ...

  6. Masonry 动画

    比如想做一个最简单的位移动画: 关键点在,改完约束后,调用下面这段代码,父view调用 layoutIfNeeded [UIView animateWithDuration:0.5 animation ...

  7. Masonry第三方代码约束

    #import "RootViewController.h" #import "Masonry.h" @interface RootViewController ...

  8. Window.requestAnimationFrame()动画更新

    概述 Window.requestAnimationFrame()方法告诉浏览器你希望执行动画,并且再下一次重绘之前要求浏览器调用一个特定的函数去更新动画.该方法把一个回调函数作为参数,该回调函数会在 ...

  9. 使用masonry手写约束

    在iOS开发过程中,手写contraints是非常痛苦的一件事情,往往那么一丢丢功能要写大量的代码,非常容易发生错误,并且非常不方便调试.所以只有在不得以的情况下才采用手工方式写contraints, ...

随机推荐

  1. NYOJ760-See LCS again,有技巧的暴力!

    See LCS again 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 There are A, B two sequences, the number of ele ...

  2. hdu 2112

    #include<stdio.h> #include<string.h> #define N 200 #define inf 999999999999 __int64 map[ ...

  3. 【BZOJ3295】动态逆序对(BIT套动态加点线段树)

    题意:对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数. 给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对 ...

  4. MYSQL常见运算符和函数【重要】

    字符函数 (1)CONCAT():字符连接 SELECT CONCAT(‘IMOOC’,’-‘,’MySQL’);//IMOOC-MySQL SELECT CONCAT (first_name,las ...

  5. 1597: [Usaco2008 Mar]土地购买 [ dp+斜率优化 ] 未完

    传送门 1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1979  Solved: 705[Subm ...

  6. POJ 3684 Physics Experiment

    和蚂蚁问题类似. #include<cstdio> #include<cstring> #include<cmath> #include<vector> ...

  7. Topcoder 658 650 point

    Topcoder 658 div2 500 加强版 不过给了<=20,暴力肯定不行. 然后想DP方程,先二分可能需要的最大次数mid; 然后根据 mid 构造 DP方程. 假设x[i]需要 x个 ...

  8. 无线网卡与本地连接不能同时使用&一机多网络的优先级设置

    无线网卡与本地连接不能同时使用&一机多网络的优先级设置 2012-05-30 20:39 初次记录 2012-08-09 10:32 修订 题目中的两个问题,其实都可以归结为一个问题,即网络优 ...

  9. iptables防火墙以及网络协议基本原理

    一. Linux 网络安全模型 1. 防火墙: 工作在主机或者网络边缘,对进出报文使用实现定义的规则进行检测,并且由匹配的规则进行处理的一组硬件或者软件.也可能两者结合. 1) 通常使用的防火墙设备 ...

  10. AspNetPager真假分页对照实例

    从開始学习BS已经有一段时间了. 对于BS的设计,都是进行的网页设计,当中包含从数据库中取出来的数据.显示在页面上.曾经在CS中,都是使用GridView等表格控件进行显示,因为数据小.并且右側又有滚 ...