一.在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,在竖直方向上仅仅设置top
和bottom
是不行的,因为它不同于UILabel,系统能通过计算UILabel的text文本得到UILabel的高度,进而系统再根据UILabel的top
和bottom
约束得到了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在竖直方向上同时设置了top
,bottom
系统会认为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地址
Demo永久下载地址:
链接: https://pan.baidu.com/s/1EAGggemx-m-6hoFdvpRAsg 提取码: stbh 复制这段内容后打开百度网盘手机App,操作更方便哦
iOS技术分享
作者:shizidy_90
链接:https://www.jianshu.com/p/6dc52081fdfd
来源:
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。