Masonry的约束布局,scrollView与cell的自动适配
公司项目使用Masonry已经很久了,上一篇中介绍了约束的原生api和Masonry的一些基础用法,还对Label等控件的自带宽高问题进行了说明。今天我写一篇实用的关于scrollView的约束布局与cell的自动适配用法。
gitHub:https://github.com/yangqingren/LBMasonry.git
我们在使用约束布局的时候,子view通常可以决定自己的size,父view是可以不参与自子view的size布局的。比如:
@interface LBView ()
@property (nonatomic,strong)UIView *subView;
@end
@implementation LBView
- (instancetype)init {
if (self = [super init]) {
[self addSubview:self.subView];
[self.subView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.mas_equalTo(self); // make. edges
make.height.mas_equalTo(100);
make.bottom.mas_equalTo(self.mas_bottom);
}];
}
return self;
}
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.lbView];
[self.view addSubview:self.lbLabel];
// self.lbView的size已经内部设置,所以不需要再次设置
[self.lbView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.offset(50);
make.right.offset(-50);
}];
// 验证self.lbView已经存在size
[self.lbLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(self.lbView);
make.top.mas_equalTo(self.lbView.mas_bottom).offset(10);
}];
// Do any additional setup after loading the view, typically from a nib.
}
// 注:Masonry的block没有被self(即调用的view)持有,所以并不需要进行weakSelf
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
self.translatesAutoresizingMaskIntoConstraints = NO;
MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
block(constraintMaker);
return [constraintMaker install];
}
// 我们自己做组件的时候也可以参考一下,做到这种效果
以上面的常见用法,引出了我在约束布局之路上的两个特殊例子:
- scrollView的约束布局
使用scrollView的时候不需要去计算其contentSize,由其子view来进行约束设置。如果你还在使用scrollView的时候设置其contentSize,直接的话的讲,就是在写死布局。
如以上例子,当约束在水平(竖直)方向是满足两个条件,即足够完成布局,比如left+width(或者left+right或者right+width)。
但是当view的父类是scrollView时,则水平和竖直方向上都需要设置满3个条件,才能完成布局,例如:
- (UIScrollView *)scrollView {
if (!_scrollView) {
// 不需要设置contentSize
_scrollView = [[UIScrollView alloc] init];
}
return _scrollView;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.scrollView];
[self.scrollView addSubview:self.view1];
[self.scrollView addSubview:self.view2];
[self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self.view);
}];
// 加上width约束scrollView的contentSize的width,让scrollView在水平方向上能够撑开
[self.view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.mas_equalTo(self.scrollView);
make.height.mas_equalTo(500);
make.width.mas_equalTo(self.view.bounds.size.width);
}];
// 加上bottom连接scrollView的底部,加上两个view的高,让scrollView在竖直方向上能够撑开
[self.view2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.view1.mas_bottom).offset(10);
make.left.right.mas_equalTo(self.scrollView);
make.height.mas_equalTo(500);
make.bottom.mas_equalTo(self.scrollView.mas_bottom).offset(-10);
}];
// Do any additional setup after loading the view, typically from a nib.
}
约束布局不需要去计算scrollView的contentSize,让代码更加易于维护。
- cell的自动算高
凡是能够使用scrollView布局的页面,tableView都能完成,比如一些表单页面,用tableView做就很方便数据的填充:
在做表单的时候,需要对不同cell进行不同的高度设置,有了cell的自动算高,这项工作就很轻松了。
首先需要给表单设置一个大约cell高度,以及设置cell的自动布局:
_tableView.estimatedRowHeight = 200;
_tableView.rowHeight = UITableViewAutomaticDimension;
// 或者是个别cell不需要自动算高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (0 == indexPath.section && 0 == indexPath.row) {
return 150;
}
return UITableViewAutomaticDimension;
}
之后在cell里面对其的高度进行有效设置(水平方向不需要设置,cell的宽度默认为tableView的宽度):
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
-
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
[self addSubview:self.textField];
// 满足竖直方向上能够表达出cell的size的约束
[self.textField mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(90);
make.edges.insets(UIEdgeInsetsMake(5, 15, 5, 15));
}];
}
return self;
}
这样building出来的表单就是可以是自动算高的了。
至此,约束布局之路基本完成,可能在之后还会写一些关于约束的更特别的用法。
当然,对于表单结构,也可设置其压缩拉伸优先级达到效果:
// 禁止拉伸优先级
[self.numLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
// 禁止压缩优先级
[self.numLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
gitHub:https://github.com/yangqingren/LBMasonry.git
end