不完整目录
1.基础篇
1.1基础使用
1.1.1运行效果
1.1.2关键代码
三个控件等高,红绿两个控件等宽
[greenView mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(redView);
make.height.mas_equalTo(blueView)
make.width.mas_equalTo(redView);
}];
黄色在蓝色中居中显示(居中偏移可使用:make.center.equalTo(blueView).centerOffset(CGPointMake(50, 50));)
make.center.equalTo(blueView);
灰色在绿色区域中设置边距
make.edges.equalTo(greenView).insets(UIEdgeInsetsMake(20, 20, 20, 20));
1.2约束百分比
1.2.1运行效果
1.2.2 关键代码
设置宽高比:multipliedBy、 dividedBy
红色高度是页面的1/2
make.height.equalTo(self.view).dividedBy(2);
绿色宽度是自身高度2倍
make.width.mas_equalTo(greenView.mas_height).multipliedBy(2);
设置绿色宽和高不能超过红色
make.width.height.mas_equalTo(redView).priorityLow();
make.width.height.lessThanOrEqualTo(redView);
1.3 UIScrollView使用Masonry
1.3.1 运行效果
1.3.2 关键代码
UIScrollView使用约束比较特殊,在添加到父视图上之后,需设置自己的大小及内容的长度。但对于scrollview和tableview,我们不能使用bottom来计算其高,因为这个属性对于scrollview和tableview来说,不用用来计算高度的,而是用于计算contentSize.height的。所以简单添加约束如下:
//设置其大小
make.edges.mas_equalTo(self.view);
// 让scrollview的contentSize随着内容的增多而变化
make.bottom.mas_equalTo(lastWidget.mas_bottom).offset(20);
这两句即可简单实现UIScrollView在页面中显示,如果页面内容高于屏幕时,可正常滑动,但内容很少时则不能滑动。解决该问题可请参照1.6正确的写法
1.4 单个约束启用、禁用
1.4.1运行效果
页面所有UILabel都设置收缩状态约束高度为40,点击某个label时,该UILabel根据内容大小动画展开,再次点击收缩。页面整体的UIScrollview根据内容高度自动扩展(原理同1.3)
1.4.2 关键代码 MASViewConstraint (void)install (void)uninstall
创建约束或更新约束时,可赋值该约束对象到itemConstraint,注意加__block
[label mas_makeConstraints:^(MASConstraintMaker *make) {
itemConstraint = (MASViewConstraint *)make.height.mas_equalTo(40);
]};
执行约束的装载或卸载,注意,当在UITableViewCell中使用时,由于cell重用的机制,约束的赋值可能存在问题
[itemConstraint install];
[itemConstraint uninstall];
1.5 UITableViewCell中使用约束,及cell高度自动计算
1.5.1运行效果
Cell布局简单来讲分为标题、描述上下两部分,其中描述文字默认收缩,点击时展开,cell高度自动扩充。
1.5.2关键代码 UITableViewCell+HDFTableViewCell
cell中指定作为最后一个视图以及最后一个视图最底部与cell的底部之间的距离
- (void)hdf_setCellLastView:(UIView *)lastView bottomOffset:(CGFloat)bottomOffset;
cell高度自动计算:静态方法自动计算cell高度 configBlock中为cell填充数据
注意:
1、hdf_setCellLastView 可以在cell初始化控件中调用,也可以在控件设置数据方法中调用。
2、cell中控件尽量不要对self.contentView.mas_bottom进行约束。除非该控件与其他控件没有top、bottom关联约束
3、cell中多行UILabel相对cell.contentView尽量使用left+width约束,避免使用left+right,后者容易产生多行文字高度计算不准确问题
4、cell中多行UILabel在iOS6上还需要设置preferredMaxLayoutWidth(项目已不关心iOS6,可忽略)。
5、项目中UITableViewCell+HDFTableViewCell 使用了cell高度的缓存,若要更新高度或者数据源做了改变,记得调用+(void)hdf_removeCellResource
1.6 UIScrollView 应用Masonry的正确用法
1.6.1运行效果
1.6.2 关键代码
scrollView设置edge约束,该约束实际上确定scrollview的frame等于当前Vc视图大小
[self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self.view);
}];
内容容器设置约束
[scrollContentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.scrollView); //scrollContentView填满Scrollview
make.width.equalTo(self.scrollView);//等同于设置contentSize宽度
make.height.greaterThanOrEqualTo(self.scrollView).offset(1);//设置contentSize高度,加1像素offset保证内容不足一屏也能滑动
}];
内容容器要知道自己到底多高,所以最后一个控件要加底部约束
[bottomWidget mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(scrollContentView.mas_bottom).offset(-80);
}];
注意:
UIScrollView 使用Masonry时,尽量不要在scrollview上直接addview。而应该使用一个viewContainer,所有的控件放在viewContainer上。
关键是 !!!设置container与scrollView之间的约束!!!。
scrollView的width或者bottom不能用来计算其Frame,因为这个属性对于scrollview和tableview来说,不用用来计算高度的,而是用于计算contentSize的
设置步骤简单来说:
1、设置scrollview的大小为屏幕大小
2、设置viewContainer宽度为scrollview宽,高度为内容高,但还要填充scrollview
1.7 UITableViewCell中隐藏控件更新布局及高度
1.7.1 运行效果
1.7.2 关键代码
cell中设置最后控件及cell高度计算同 “1.5简单tableview布局”
分为两种情况,如果需要隐藏的控件高度是固定或是frame封装的控件(如果要隐藏的控制在最低端则直接调用hdf_setCellLastView即可,记得将其hidden掉)
if (isHidden) {
[_testCustomView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.equalTo(@0);
}];
}else{
[_testCustomView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.equalTo(@100);
}];
}
控件内容非固定,根据内容变化 实现原理是直接把下方控件顶部约束贴到该控件顶部,由于是remake方式,所以原有约束需保留
if (isHidden) {
testCustomView.hidden = YES;
[self.bottomWidget mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(_testCustomView.mas_top);
make.centerX.equalTo(@0);
}];
}else{
testCustomView.hidden = NO;
[self.bottomWidget mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(_testCustomView.mas_bottom);
make.centerX.equalTo(@0);
}];
}
2.动画篇
2.1动画更新、重建约束
2.1.1 运行效果
2.1.2关键代码
updateViewConstraints setNeedsUpdateConstraints
页面中重写updateViewConstraints方法,当然即使不用该回调也可以实现动画,但苹果推荐在updateViewConstraints方法中更新、添加、重建约束;
当我们将update或remake约束代码放到updateViewConstraints这个方法中时,我们在viewDidLoad方法中可以不用再写约束
-(void)updateViewConstraints{
[super updateViewConstraints] 父类方法一定要调用
}
想要更新约束时添加动画,就需要调用关键的一行代码:setNeedsUpdateConstraints,这是选择对应的视图中的约束需要更新。
对于updateConstraintsIfNeeded这个方法并不是必须的,但是有时候不调用就无法起到我们的效果。但是,官方都是这么写的,从约束的更新原理上讲,这应该写上。我们要使约束立即生效,就必须调用layoutIfNeeded此方法。看下面的方法,就是动画更新约束的核心代码
-(void)startAnimation{
//告诉self.view约束需要更新
[self.view setNeedsUpdateConstraints];
//告诉self.view检测是否需要更新约束,若需要则更新,下面添加动画效果才起作用
[self.view updateConstraintsIfNeeded];
//frame更新,执行动画
[UIView animateWithDuration:0.3 animations:^{
[self.view layoutIfNeeded];
}];
}
3.应用篇
3.1 tableHeaderView使用Masonry
3.1.1运行效果
对于一些页面中使用UITableView时,如果头部布局较固定,个人建议使用tableHeaderView,利于代码结构及UI调整。
3.1.2关键代码 layoutIfNeeded
使用frame定义一个customeHeaderView,之所以使用frame是由于tableHeaderView只支持frame来使用,因此不要对customeHeaderView添加约束
customeHeaderView = [[UIView alloc] initWithFrame:(CGRect){0,0,kScreenWidth,100}];
注意!!设置宽度为屏幕宽度而不是0,避免子控件设置宽度约束而报约束冲突警告
customeHeaderView中正常使用Masonry来添加子控件
调用tableView.tableHeaderView = customeHeaderView时,要放在最后。原因很简单:赋予正确的frame
-(void)updateTabelHeaderHeight{
[customeHeaderView layoutIfNeeded];
CGRect headerRect = customeHeaderView.frame;
headerRect.size.height = bottomWidget.frame.origin.y+ bottomWidget.frame.size.height;
customeHeaderView.frame = headerRect;
tableView.tableHeaderView = customeHeaderView;
}当customeHeaderView中高度需要动态变化时,需重新调用上面updateTabelHeaderHeight方法
3.2 内容相对多个控件布局
3.2.1运行效果
(只有一个科室时,图一文字垂直居中显示,图二垂直上对齐)
3.2.2 关键代码
底部绿色Label设置约束为:
make.top.greaterThanOrEqualTo(ivAvatar.mas_bottom).offset(15);
make.top.equalTo(lblVerticalDesc.mas_bottom).offset(15);
如果想要科室文字垂直上对齐如图二,则都设置为greaterThanOrEqualTo
3.3文字区域等宽
3.3.1运行效果
3.3.2关键代码
[lblNum1 mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(@15);
make.left.equalTo(ivAvatar.mas_right);
make.width.mas_equalTo(@[lblNum2, lblNum3]);//可以传数组
}];
3.4同向文字显示优先级
3.4.1运行效果
3.4.2关键代码 setContentHuggingPriority setContentCompressionResistancePriority
这两个方法是AutoLayout的api,Masonry是基于AutoLayout的封装。所以可以混合使用,可设置优先级及方向。
ContentCompressionResistance=不许挤我。这个属性的优先级(Priority)越高,越不“容易”被压缩,也就是说,当整体的空间装不下所有的View的时候,ContentCompressionResistance优先级越高的,显示的内容越完整
ContentHugging = 抱紧。 这个属性的优先级越高,整个View就要越“抱紧”View里面的内容。也就是View的大小不会随着父级View的扩大而扩大
[lblHorizontalDesc setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
[lblHorizontalDesc setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
4.问题篇
1、view一定是已经被首先addSubview的(不可以直接对tableHaderView进行约束)
2、约束的设置其实就是告诉系统你的控件各自的相对位置,也就是系统能计算出每个控件的实际frame
3、控制UItableViewCell中控件的高度或调整约束就可以动态适用cell高度计算,
4、cell中控件尽量不要对cell.contentView进行mas_bottom约束,除非这个控件没有mas_top约束;
5、cell中多行的UIlabel使用left、right约束有时会有UILabel高度计算不准确的问题,建议使用left+width;
6、使用Masonry的理念就是不用去计算文字的宽度及高度,如果需要自己计算,看看是不是约束能优化
7、一些基本的控件有内容时可不用设置高度约束,如:UILabel,UIimageView,UIButton等
demo下载链接: