Masonry 动画更新约束

时间:2021-07-07 18:04:59

前言

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

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

效果图

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

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. 39:第n小的质数

    39:第n小的质数    总时间限制:    1000ms    内存限制:    65536kB描述    输入一个正整数n,求第n小的质数.输入    一个不超过10000的正整数n.输出    ...

  2. [Javascript] Chaining the Array map and filter methods

    Both map and filter do not modify the array. Instead they return a new array of the results. Because ...

  3. python 自定义回调函数

    回调函数用起来比较爽.特别是在js中,满世界全是回调,那么在python中,怎么来优雅地实现自己的回调函数呢 下面贴一个我写的例子 class BaseHandler(object): def cra ...

  4. 在linux服务器上搭建nvidia-docker环境

    docker相当于一个容器,其可以根据你所需要的运行环境构建相应的运行环境,此时各个环境之间彼此隔离,就不会存在在需要跑一个新的代码的时候破坏原来跑的代码所需要的环境,各个环境之间彼此隔离开,好像一个 ...

  5. python 常用的模块

    面试的过程中经常被问到使用过那些python模块,然后我大脑就出现了一片空白各种模块一顿说,其实一点顺序也没有然后给面试官造成的印象就是自己是否真实的用到这些模块,所以总结下自己实际工作中常用的模块: ...

  6. Vue 入门之 Vuex 实战

    Vue 入门之 Vuex 实战 引言 Vue 组件化做的确实非常彻底,它独有的 vue 单文件组件也是做的非常有特色.组件化的同时带来的是:组件之间的数据共享和通信的难题. 尤其 Vue 组件设计的就 ...

  7. tomcat和java环境

    mac tomcat http://blog.csdn.net/huyisu/article/details/38372663 mac jdk 1.8 http://wlb.wlb.blog.163. ...

  8. GIS-005-Dojo & jQuery 事件处理

    1.添加事件 dojo.connect(dojo.byId("SelectRect"), "onclick", function () { //todo }); ...

  9. 2018 Multi-University Training Contest 8 Solution

    A - Character Encoding 题意:用m个$0-n-1$的数去构成k,求方案数 思路:当没有0-n-1这个条件是答案为C(k+m-1, m-1),减去有大于的关于n的情况,当有i个n时 ...

  10. easyui combotree 异步树 前端写法js

    简要说下使用场景: combotree下拉框第一次加载时,请求一个接口,页面上展示顶层节点们(可以理解为最顶层的节点,比如所有的一级公司): 当点击其中一个节点前面的小三角展开时,再次请求服务器接口( ...