一、label约束:网络
1)、只需约束x、y 点相关就行。宽高 长度相关不用约束,就算用boundingRectWithSize计算出来的,也可能不许。less
如:top、bottom二选一,trailing、leading二选一,或者center,宽高会自动生成。(同时约束trailing、leading的话,至关于设了宽度)ide
2)、有些地方怕label过长超出,或覆盖其余控件,这时就须要约束 宽高,让其“...”。布局
后续补充:仍是不必约束宽,可让top、bottom、trailing、leading设置 lessThanOrEqualTo 属性。字体
小于正常显示,大于会省略号,比起 equalTo 宽,写死的,会好用些动画
好比高写死的话,会发现,字体垂直居中,这样就和左边的“标题Label”,水平不对齐了ui
1)、lessThanOrEqualTo:小于或等于(注意负号)( label 有个最大宽度属性 preferredMaxLayoutWidth,有点像? )atom
2)、equalTo:等价于spa
3)、greaterThanOrEqualTo:大于或等于(注意负号)对象
3)、垂直约束,我更喜欢用centerY。
用top的话:1)、UI的字体大小和iOS可能会有误差,多行label,偏差就越大。而设中心点,他是中心定点,上下伸缩。
2)、若是又有一个控件,如ImageView,跟label的Y轴中心对齐,而label,用top对齐其余且当前label.text = nil,会出错(好像此时label的center会等于top)。
二、在cell重用里刷新数据,要用更新约束:mas_updateConstraints 或 从新约束:mas_remakeConstraints。
后续补充:3种经常使用
1)、mas_makeConstraints:约束
2)、mas_updateConstraints:更新相同的约束对象数据,如宽。
3)、mas_remakeConstraints:从新约束全部
再补充:也不必一直在cell里改约束。好比,cell里常常修改一个label的约束的时候,
1)、能够考虑多弄几个样式的label,当前不须要的label隐藏。
2)、能够经过 安装、卸载 。在初始化的时候,定好约束优先级。
三、UIPageControl小圆点、UISwitch开关,约束 center/ top、bottom / trailing、leading 等x、y 点便可。
四、约束centerX/centerY,容易犯的错
make.centerX.mas_equalTo(10.0); make.centerX.offset(10.0);
语句看起来,像是给centerX = 10.0的数值,然而效果倒是父视图的centerX + 10.0,
缘由,参照下面的附录,它自动默认同样的属性。应该写详细点。
make.centerX.mas_equalTo(self.view.mas_leading).offset(10.0);
再补充:若是1个固定的控件和1个移动的控件(下划线)centerX,约束同样,如,make.centerX.mas_equalTo(固定.mas_centerX),
接着,想经过mas_updata,更新centerX到另外一个控件,会发现约束冲突,连固定的控件一块儿移动。
解决,取另外一个参照物。
1)、newCenterX = 另外一个控件.centerX 。
2)、make.centerX.mas_equalTo(固定.mas_leading).offset(newCenterX)
五、属性
1)、以前用得较多的:top、bottom、trailing、leading、center、width、height
2)、如今开始用的 edges == top、bottom、trailing、leading。
insets 在 边界约束好的基础上,设置与父视图的间隙,为正值!!也能够直接在edges里设置,同样。
size == width、height。
sizeOffset 在 size 约束好的基础上,进行增+减-。主要用于相对另外一个View。
multipliedBy 倍数,好比0.五、1.5。不局限在相同属性,也能够设置为自身 width 为 height 的3倍。
3)、center 配合 size 不错。就像layer的 position 和 bound 。
六、父视图contentView的宽高,有时候能够不用设置,它会根据子类去约束,好比移除某个子View,自动缩小、变化。
同时,也要注意由于父视图缺乏约束,而形成的“自动变化Bug”。
七、优先级 与 动画( .priority(500) 或 UILayoutPriority 常量 )
在同一个控件作约束,能够设置两个相同属性的约束,对其优先级进行设置,会先找优先级高的约束。
优先级高约束有问题,会再向下寻找次之优先级的属性约束。
默认优先级 UILayoutPriorityRequired == 1000 。
后续补充:同一属性、同一优先级,多个约束也没问题。不过都得是greaterThanOrEqualTo、lessThanOrEqualTo的约束。
使用参照“八、优先级与边界”。
再补充:好比网络请求,加载到数据,给当前内容为nil的控件写入数据的时候(例如,当前 空的昵称label、空的性别图片 ,没显示出来)
多写一行 UIView animation + layoutIfNeeded ,有意想不到的效果。
对 再补充 补充:使用 UIView animation + layoutIfNeeded 作动画的状况下,
可以使用 [self.animationView.layer removeAllAnimations]; 移除动画,如需可用 block 的 finished 判断是否完成动画
[UIView animateWithDuration:8.0
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
// 动画
[self layoutIfNeeded];
} completion:^(BOOL finished) {
// 动画完成
[self.animationView mas_updateConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(SCREEN_WIDTH);
}];
}];
再再补充:作弹窗动画,若是初始化为约束,作动画也用 约束+ UIView animation + layoutIfNeeded,在第一次(懒)加载的时候会致使全部的控件一块儿动画,
可先在初始化的时候 [self setNeedsLayout] + [self layoutIfNeeded] ,完成UI布局。
1)、如 移除优先级高的参照物,再layout。就能够作动画。
[view mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.equalTo(参照物1.mas_trailing).offset(20).priority(750); make.leading.equalTo(参照物2.mas_trailing).offset(20).priority(250); }]; [参照物1 removeFromSuperview]; [UIView animateWithDuration:1.0 animations:^{ [self.view layoutIfNeeded]; }];
2)、或者提取出来
2-1)、卸载掉该约束
MASConstraint *leadingMas; [view mas_makeConstraints:^(MASConstraintMaker *make) { leadingMas = make.leading.equalTo(参照物1.mas_trailing).offset(20).priority(750); make.leading.equalTo(参照物2.mas_trailing).offset(20).priority(250); }]; [leadingMas uninstall]; [UIView animateWithDuration:1.0 animations:^{ [self.view layoutIfNeeded]; }];
后续补充:卸载uninstall、安装install 能够重复。只要变量没释放
2-2)、修改约束。
MASConstraint *widthMas; [view mas_makeConstraints:^(MASConstraintMaker *make) { widthMas = make.width.equalTo(50); }]; widthMas.equalTo(100); [UIView animateWithDuration:1.0 animations:^{ [self.view layoutIfNeeded]; }];
3)、也能够用 mas_updateConstraints 对同一属性进行更新
[view mas_updateConstraints:^(MASConstraintMaker *make) { make.width.equalTo(100); }]; [UIView animateWithDuration:1.0 animations:^{ [self.view layoutIfNeeded]; }];
八、优先级与边界
1)、初始化
@property (nonatomic,strong) MASConstraint *topMas; @property (nonatomic,strong) MASConstraint *leadingMas; [self.moveView mas_makeConstraints:^(MASConstraintMaker *make) { // 边界。不写优先级,默认优先级最高 = UILayoutPriorityRequired = 1000 make.leading.top.greaterThanOrEqualTo(self.bgView); make.trailing.bottom.lessThanOrEqualTo(self.bgView); // 肯定宽高 make.width.mas_equalTo(50); make.height.mas_equalTo(50); // 肯定位置。高优先级,可变更的位置。 self.topMas = make.top.equalTo(self.bgView).offset(50).priority(750); self.leadingMas = make.leading.equalTo(self.bgView).offset(50).priority(750); }];
后续补充:宽高看状况判断是否须要约束。
2)、改变位置
2-1)、改动 make 返回的数据
self.topMas.offset(100); self.leadingMas.offset(100);
2-2)、直接更新约束
[self.moveView mas_updateConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.bgView).offset(100).priority(750); make.leading.mas_equalTo(self.bgView).offset(100).priority(750); }];
补充,2-1)比 2-2)须要多存2个变量,且只能修改offset,没法改以前的参照物、优先级。
可是,写法更简洁,适合改动少的。
优先级,能够自定宏,也能够用系统给 UILayoutPriorityDefaultHigh = 750 、UILayoutPriorityDefaultLow = 250。
再补充:边界,也能够在拖动的时候判断x、y、x+width、y+height,纯手工计算。
九、若是两个并排的lable。
1)、在字数(宽高)可能相互挤压的时候,能够优先保护某个Label的完整性
// 水平位置,优先级高 [label1 setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal]; // 水平位置,优先级低(会被挤压) [label2 setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
后续补充:setContentCompressionResistancePriority 为UIView的方法,设置抗压性 优先级,第二个参数可选水平、垂直方向。
CompressionResistance 抗压越高,则越不会被挤压,如lable被挤压,会显示“...”。
相对的,有个 setContentHuggingPriority ,拥抱优先级,没用过,应该是优先级越高,越不会被拉伸之类的把?!
2)、字体较少的时候,较空的地方能够用 lessThanOrEqualTo 。留空。
十、一些只要约束 位置 ,自动生成长宽的控件,如label,能够重写 intrinsicContentSize ,添加内边距,增大。
- (CGSize)intrinsicContentSize { CGSize tempSize = [super intrinsicContentSize]; return CGSizeMake(tempSize.width + insets.left + insets.right, tempSize.height + insets.top + insets.bottom); }
十一、自动顶住 导航栏或状态栏 , tabbar或底部
// self.mas_topLayoutGuide; // self.mas_bottomLayoutGuide; // self.mas_topLayoutGuideTop; // self.mas_topLayoutGuideBottom; // self.mas_bottomLayoutGuideTop; // self.mas_bottomLayoutGuideBottom; make.top.mas_equalTo(self.mas_topLayoutGuide);
十二、baseLine。
不大熟悉。好像主要应用于,对齐两个View里的子Lable,从而约束到View的位置。
重写、以返回要对齐的baseView
iOS(6.0 - 9.0)
- (UIView *)viewForBaselineLayout { return baseView; }
iOS(9.0 - )
- (UIView *)viewForFirstBaselineLayout{ return baseView; } - (UIView *)viewForLastBaselineLayout{ return baseView; }
1三、scrollView约束
scrollView,可视范围正常约束,如:
[scrollView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.view); }];
contentView,约束,以下(高度可变):
[scrollView addSubview:contentView]; [contentView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(scrollView); make.width.equalTo(scrollView); make.height.greaterThanOrEqualTo(@(0.f)); }];
须要的items,添加、约束到contentView上。
后续补充:忘了写了,最后一个item的bottom要和contentView的bottom约束上,contentView才有肯定的高
1四、获取上面刚约束完的尺寸,来设置别的view.frame。要先layout,不然可能获取到{0, 0, 0, 0}。
[self layoutIfNeeded];
附录:
例、两个并排的按钮
//equalTo 比较 View, //mas_equalTo 比较 数值 //若是在 redButton 里约束有用到 greenButton ,则 greenButton 在以前就要添加到和 redButton 同一父类View下。 红色的按钮(equalTo) UIButton *redButton = [[UIButton alloc]init]; redButton.backgroundColor = [UIColor redColor]; [self.view addSubview:redButton]; [redButton mas_makeConstraints:^(MASConstraintMaker *make) { make.height.equalTo(@100); make.leading.equalTo(self.view).offset(10.0); make.bottom.equalTo(self.view).offset(-10.0); }]; 绿色的按钮(mas_equalTo) 1)、比较全的写法 UIButton *greenButton = [[UIButton alloc]init]; greenButton.backgroundColor = [UIColor greenColor]; [self.view addSubview:greenButton]; [greenButton mas_makeConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(100); make.width.mas_equalTo(redButton.mas_width); make.trailing.mas_equalTo(self.view.mas_trailing).offset(-10.0); make.bottom.mas_equalTo(self.view.mas_bottom).offset(-10.0); make.leading.mas_equalTo(redButton.mas_trailing).offset(10.0); }]; 2)、若是属性是同样的,能够省略后面的属性 make.width.mas_equalTo(redButton); make.trailing.mas_equalTo(self.view).offset(-10.0); make.bottom.mas_equalTo(self.view).offset(-10.0); 3)、相对于(2),甚至能够写0,相对父视图。宽可不能跟着写0,宽0就0了 make.trailing.mas_equalTo(0).offset(-10.0); make.bottom.mas_equalTo(0).offset(-10.0); 4)、相对于(3),既然均可以0,那干脆直接去掉 make.trailing.offset(-10.0); make.bottom.offset(-10.0);