UITableViewCell高度自適應探索--UITableView+FDTemplateLayoutCell
地址: http://www.jianshu.com/p/7839e3a273a6
UITableViewCell高度自適應探索--cell預估高度(一)
地址: http://www.jianshu.com/p/6ab92579fcf1
UITableViewCell高度自適應探索--cell預估高度(二)
地址: http://www.jianshu.com/p/f3609cd9392e
今天,再提供一種AutoLayout與Frame相結合的方式來設置cell高度的方法.git
今天這個方法的要點是:github
相對於以前說的那些方法,這個方法比UITableView+FDTemplateLayoutCell使用起來更簡單和容易理解(自從寫FD那篇文章發表後收到不少網友的關於使用的問題,大部分是因爲沒有使用正確);而且克服了預估高度方式的那些問題,也不用把約束改來改去, 使計算的過程更加可控.緩存
這種方法雖然是使用fram的方式計算,可是若是沒有autoLayout,計算的過程就會複雜幾倍,有時候可能還須要一個專門的類去管理子控件的frame.在我看來是一個比較不錯的方法.ide
進入正題.佈局
先看要實現的效果:atom
其中文字的長度不一,圖片可能有或沒有.爲了排除其餘干擾,數據來自plist文件.spa
1 @interface Message : NSObject 2 3 // 頭像、名字、和描述文字我給固定了,因此沒有弄屬性處理 4 @property (nonatomic, copy) NSString *imageName; 5 @property (nonatomic, copy) NSString *content; 6 @property (nonatomic, assign, readonly) CGFloat cellHeight; 7 8 @end
1 - (CGFloat)cellHeight { 2 if (!_cellHeight) { 3 CGFloat contentW = [UIScreen mainScreen].bounds.size.width - 2 * margin; // 屏幕寬度減去左右間距 4 CGFloat contentH = [self.content boundingRectWithSize:CGSizeMake(contentW, MAXFLOAT) 5 options:NSStringDrawingUsesLineFragmentOrigin 6 attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:contentFont]} 7 context:nil].size.height; 8 _cellHeight = contentLabelY + contentH + margin; 9 } 10 return _cellHeight; 11 }
上面高度的計算尚未將內容圖片的高度計算在內. 而且實現了利用模型的cellHeight屬性緩存第一次計算高度.
1 // 屬性聲明 2 @property (strong, nonatomic) UIImageView *contentImageView; 3 // getter實現 4 - (UIImageView *)contentImageView { 5 if (!_contentImageView) { 6 _contentImageView = [[UIImageView alloc] init]; 7 [self.contentView addSubview:_contentImageView]; 8 } 9 return _contentImageView; 10 }
1 @property (nonatomic, strong) Message *message; 2 - (void)setMessage:(Message *)message { 3 _message = message; 4 self.contentLabel.text = _message.content; 5 if (message.imageName.length) { 6 self.contentImageView.hidden = NO; 7 self.contentImageView.image = [UIImage imageNamed:message.imageName]; 8 } 9 else { 10 self.contentImageView.hidden = YES; 11 } 12 }
固然,這時候contentImageView固然是顯示不出來的,由於咱們尚未贈送它一個frame.那麼它的frame從何而來呢?code
一開始咱們說過,計算要基於模型,因此接下來的思路是由模型算出imageView的frame,拿去給cell用.blog
回到模型cellHeight的getter方法,添加對imageName屬性的處理:圖片
1 // 圖片將要展現的frame做爲模型的其中一個屬性 2 @property (nonatomic, assign) CGRect contentImageFrame; 3 - (CGFloat)cellHeight { 4 if (!_cellHeight) { 5 CGFloat contentW = [UIScreen mainScreen].bounds.size.width - 2 * margin; // 屏幕寬度減去左右間距 6 CGFloat contentH = [self.content boundingRectWithSize:CGSizeMake(contentW, MAXFLOAT) 7 options:NSStringDrawingUsesLineFragmentOrigin 8 attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:contentFont]} 9 context:nil].size.height; 10 _cellHeight = contentLabelY + contentH + margin; 11 12 // 對imageName屬性的處理 13 if (self.imageName.length) { 14 UIImage *image = [UIImage imageNamed:self.imageName]; 15 CGFloat imageH = image.size.height; 16 CGFloat imageW = image.size.width; 17 // 直接得出contentImageView應該顯示的frame 18 _contentImageFrame = CGRectMake(margin, _cellHeight, imageW, imageH); 19 _cellHeight += imageH + margin; 20 } 21 } 22 return _cellHeight; 23 }
當上面代碼執行完畢,contentImageFrame就有值了.接着,回到cell的setMessage:方法給contentImageView賦值.
1 - (void)setMessage:(Message *)message { 2 _message = message; 3 self.contentLabel.text = _message.content; 4 if (message.imageName.length) { 5 self.contentImageView.hidden = NO; 6 self.contentImageView.image = [UIImage imageNamed:message.imageName]; 7 // 給圖片的frame賦值,這個值就是上面獲得那個 8 self.contentImageView.frame = _message.contentImageFrame; 9 } 10 else { 11 self.contentImageView.hidden = YES; 12 } 13 }
1 // 控制器tableView協議方法實現 2 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 3 Message *message = self.dataList[indexPath.row]; 4 return message.cellHeight; 5 }
完整代碼下載:https://github.com/CoderAO/AutoCellHeightMix