Masonry实现cell自动行高

一.在iOS8之前要实现iOS列表页的cell的不定行高时,只能由开发者根据网络请求返回的数据自行计算行高,对于统一行高或者cell的contentView上没有太多子控件时,或许还算简单,但是一旦cell中有大量的子控件需要一个个添加位置的相互依赖,甚至再有不定字数的text文本时,手动设置约束将会耗费大量的体力和时间。
二.或许苹果也感受到了这方面的痛点,于是在iOS8中,加入了自动布局AutoLayout,但是系统原生的AutoLayout类用起来相当繁重,好在开发者可以选择Masonry,一个优秀的开源库,它是对系统的AutoLayout的封装。

举个UITableViewCell UILabel的高度自适应例子,从iOS8起,我们就可以这样做,首先设置tableView

_tableView.estimatedRowHeight = '你的estimatedRowHeight值';
_tableView.rowHeight = UITableViewAutomaticDimension;

然后在我们自定义的cell里实例化UILabel,注意,UILabel的numberOfLines = 0属性一定要设置,不然UILabel的自适应高度就无从谈起了

_label = [[UILabel alloc] init];
_label.font = [UIFont systemFontOfSize:16];
_label.numberOfLines = 0;
[self.contentView addSubview:_nameLabel];

然后设置label的constraints,我们只需要设置好label的上,下,左,右,无需显式设置它的height,它的height将由系统自动计算

[self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.mas_equalTo(10);
        make.right.mas_equalTo(-10);
        make.bottom.mas_equalTo(-10);
 }];

或者

[self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.mas_equalTo(UIEdgeInsetsMake(10, 10, 10, 10));
}];

然后根据后台返回给label的text赋值即可,对于我们开发者而言,省去了手动计算label的text高度,也无需再实现tableView的delegate的heightForRowAtIndexPath的方法

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
}

除了UILabel的自适应高度,其他控件设置好constraints也能让系统自动计算cell高度,例如我们的cell里有一个UIImageView控件,同样前提设置好tableView

_tableView.estimatedRowHeight = '你的estimatedRowHeight值';
_tableView.rowHeight = UITableViewAutomaticDimension;

然后在你的自定义tableViewCell里

_iconView = [[UIImageView alloc] init];
[self.contentView addSubview:_iconView];
[self.iconView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(10);
            make.top.mas_equalTo(10);
            make.width.mas_equalTo(50);
            make.bottom.mas_equalTo(-10);
}];

但是对于UIImageView,在竖直方向上仅仅设置topbottom是不行的,因为它不同于UILabel,系统能通过计算UILabel的text文本得到UILabel的高度,进而系统再根据UILabel的topbottom约束得到了cell的高度,而系统并不知道UIImageView的height(好似鸡生蛋,蛋生鸡的问题),所以,我们还要给出UIImageView的height约束

 [self.iconView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(10);
            make.top.mas_equalTo(10);
            make.width.mas_equalTo(50);
            make.bottom.mas_equalTo(-10);
            make.height.mas_equalTo(50);
 }];

但是当我们运行起来之后,系统会打印出来约束告警,提示约束有冲突

[LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "",
    "",
    "",
    ""
)

Will attempt to recover by breaking constraint 


Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in  may also be helpful.

这个约束冲突告警不会影响运行,但是毕竟是有约束冲突问题,因为UIImageView在竖直方向上同时设置了topbottom系统会认为UIImageView的height无需再设定,然后就与我们显式设置的height约束冲突了,怎么解决冲突呢,我们可以以设置约束优先级来解决

 [self.iconView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(10);
            make.top.mas_equalTo(10);
            make.width.mas_equalTo(50);
            make.bottom.mas_equalTo(-10);
            make.height.mas_equalTo(50).priorityHigh();
 }];

Demo GitHub地址

你可能感兴趣的:(Masonry实现cell自动行高)