-------推薦使用最下方的【改進(jìn)】方法-------
(前排補(bǔ)上一個(gè)簡(jiǎn)單的小Demo:https://github.com/3KK3/AutoFitDemo/tree/master
時(shí)間倉(cāng)促,有些許不足,敬請(qǐng)見(jiàn)諒。)
方法一:
對(duì)cell的subview增加針對(duì)于
contentView的約束(注意設(shè)置文字的最大寬度);設(shè)置tableview預(yù)估高度
estimateHeight在cell拿到數(shù)據(jù)的地方
cellForRowAtIndexPath,進(jìn)行強(qiáng)制刷新布局:先根據(jù)數(shù)據(jù)和cell控件要求計(jì)算實(shí)際高度,并存入dataModel模型(做緩存),然后調(diào)用方法[self layoutIfNeeded](第一次顯示內(nèi)容的時(shí)候 無(wú)需調(diào)用setNeedsLayout),這樣heightForIndexPath會(huì)緊隨其后獲取cell的真實(shí)高度,此時(shí)存入模型的cell的高度就起了作用了
PS:
預(yù)估高度機(jī)制 啟用后 改變cell的加載順序
原來(lái)的順序 : 先調(diào)用
heightForRowAtIndexPath獲取真實(shí)高度,拿到高度之后再調(diào)用cellForRowAtIndexPath渲染cell內(nèi)容啟用預(yù)估高度之后:先調(diào)用
estimatedHeightForRowAtIndexPath返回代理估計(jì)高度,然后再根據(jù)預(yù)估高度調(diào)用cellForRowAtIndexPath渲染cell內(nèi)容,同時(shí)計(jì)算真實(shí)高度,最后再調(diào)用heightForRowAtIndexPath拿到計(jì)算的真實(shí)高度 顯示
方法二:
對(duì)cell的subview增加針對(duì)于contentView的約束(注意設(shè)置文字的最大寬度)
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
//只創(chuàng)建一個(gè)cell用作測(cè)量高度
static MyCell *cell = nil;
if (!cell) cell = [self.tableView dequeueReusableCellWithIdentifier:@"MyCell"];
//這里把數(shù)據(jù)設(shè)置給Cell
cell.titleLabel.text = [_dataSource objectAtIndex:indexPath.row];
[cell layoutIfNeeded];
[cell updateConstraintsIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height;
}
方法三:
1.在cell中設(shè)置多行l(wèi)abel的約束:
// 計(jì)算UILabel的preferredMaxLayoutWidth值,多行時(shí)必須設(shè)置這個(gè)值,否則系統(tǒng)無(wú)法決定Label的寬度
CGFloat preferredMaxWidth = [UIScreen mainScreen].bounds.size.width - (16 + 4) * 2 - 44 - 4;
// Content - 多行
_contentLabel = [UILabel new];
_contentLabel.numberOfLines = 0;
_contentLabel.preferredMaxLayoutWidth = preferredMaxWidth; // 多行時(shí)必須設(shè)置
[self.contentView addSubview:_contentLabel];
[_contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(_titleLabel.mas_bottom).with.offset(4);
make.left.equalTo(_avatarImageView.mas_right).with.offset(4);
make.right.equalTo(self.contentView).with.offset(-4);
make.bottom.equalTo(self.contentView).with.offset(-4);}
];
// 設(shè)置高度的Content Hugging
[_contentLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
2.UITableView
再看看UITableView。
用systemLayoutSizeFittingSize:獲取Cell的高度
在設(shè)定好Cell的約束以后,就可以用systemLayoutSizeFittingSize:方法獲取Cell的實(shí)際高度,它的參數(shù)可以設(shè)定為兩個(gè)系統(tǒng)常量,如下:
UILayoutFittingCompressedSize: 返回合適的最小大小。
UILayoutFittingExpandedSize: 返回合適的最大大小。
為了在“- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath ”方法中計(jì)算Cell的高度,我們需要一個(gè)專(zhuān)門(mén)用于計(jì)算高度的Cell實(shí)例,可以說(shuō)算是Cell的“模板”。一般來(lái)說(shuō),這個(gè)實(shí)例可以設(shè)置成函數(shù)的static變量,并只在第一次使用時(shí)初始化一次。
model簡(jiǎn)單緩存高度
為了避免每次滑動(dòng)時(shí)計(jì)算高度,可以將Cell的高度緩存下來(lái)。如,保存在每一行對(duì)應(yīng)的數(shù)據(jù)Model(Entity)中,例如:
@interface Entity : NSObject
// Data
@property (copy, nonatomic) NSString *title;
// ...// Cache height
@property (assign, nonatomic) CGFloat cellHeight;
@end
tableView代理方法中代碼:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
static Case4Cell *templateCell; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ templateCell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([Case4Cell class])]; });
// 獲取對(duì)應(yīng)的數(shù)據(jù)
Case4DataEntity *dataEntity = _data[(NSUInteger) indexPath.row];
// 填充數(shù)據(jù)
[templateCell setupData:dataEntity];
// 判斷高度是否已經(jīng)計(jì)算過(guò)
if (dataEntity.cellHeight <= 0) {
// 根據(jù)當(dāng)前數(shù)據(jù),計(jì)算Cell的高度,
// ------ 注意+1 ------
dataEntity.cellHeight = [templateCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 1;
}
return dataEntity.cellHeight;
}
改進(jìn):
iOS 8的新特性
iOS 8大大簡(jiǎn)化了Cell的高度計(jì)算,只要:
1.設(shè)置好Cell中控件的約束;
- 然后 UITabelView初始化時(shí)候:
// UITabelView初始化時(shí)候
tableView.rowHeight = UITableViewAutomaticDimension;
tableView.estimatedRowHeight = 80;
3.在UITableview 代理方法:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// 只用返回這個(gè)!
return UITableViewAutomaticDimension;
}