UITableViewCell 高度自適應(yīng)

UITableViewCell 高度自適應(yīng)一直是我們做動(dòng)態(tài)Cell高度時(shí)遇到的最煩躁的問題,Cell動(dòng)態(tài)高度計(jì)算可以去看看sunny的這篇文章介紹,今天主要和大家分享下我在使用systemLayoutSizeFittingSize系統(tǒng)自帶方法計(jì)算高度的一些心得!

Demo gif

ZHAutoCalculateCellHeight.gif

先看原函數(shù)注釋

/* The size fitting most closely to targetSize in which the receiver's subtree can be laid out while optimally satisfying the constraints. If you want the smallest possible size, pass UILayoutFittingCompressedSize; for the largest possible size, pass UILayoutFittingExpandedSize.
 Also see the comment for UILayoutPriorityFittingSizeLevel.
 */
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize NS_AVAILABLE_IOS(6_0); // Equivalent to sending -systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority: with UILayoutPriorityFittingSizeLevel for both priorities.

從注釋中我們可以看出,當(dāng)你的約束條件配置好后它可以計(jì)算出最接近目標(biāo)的Size,那我們?cè)撊绾蜗率帜?

1.首先我們需要建一個(gè)UITableViewCell

假如我們Cell的布局如下所示:

屏幕快照 2016-09-08 17.08.11.png

Cell所對(duì)應(yīng)的Class我們?nèi)∶麨?code>ZHCalculateTableViewCell
所帶屬性我們定義為:

@interface ZHCalculateTableViewCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UILabel *TitleLabel;
@property (weak, nonatomic) IBOutlet UILabel *ContentLabel;
@property (weak, nonatomic) IBOutlet UIImageView *showImgView;
@property (weak, nonatomic) IBOutlet UILabel *UseNameLabel;
@property (weak, nonatomic) IBOutlet UILabel *TimeLabel;
@property (strong, nonatomic) ZHCalculateHeightModel *model;
@end

看到這里也許你會(huì)疑惑ZHCalculateHeightModel是什么,它是我們Cell所要展示的數(shù)據(jù)來源!

2.然后我們?yōu)槲覀兊腃ell建個(gè)數(shù)據(jù)模型

Cell的模型名稱我們暫定為:ZHCalculateHeightModel
所帶屬性:

@interface ZHCalculateHeightModel : NSObject
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *content;
@property (nonatomic, strong) NSString *username;
@property (nonatomic, strong) NSString *time;
@property (nonatomic, strong) NSString *imageName;

Ok,數(shù)據(jù)模型建立好了,展示的TableViewCell也有了, Just Show it~

3. 建一個(gè)繼承于UITableViewControllerZHCustomLayoutTableViewController

  • 建一個(gè)在函數(shù)-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath中調(diào)用的Cell:
@property (nonatomic, strong)  ZHCalculateTableViewCell *prototypeCell;
  • 注冊(cè)Cell
[self.tableView registerNib:[UINib nibWithNibName:@"ZHCalculateTableViewCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:CellIdentifier];
self.tableView.estimatedRowHeight = 100;//很重要保障滑動(dòng)流暢性
self.prototypeCell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];

  • 動(dòng)態(tài)計(jì)算高度
  -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{

    ZHCalculateTableViewCell *cell = self.prototypeCell;
    cell.contentView.translatesAutoresizingMaskIntoConstraints = NO;
    [self configureCell:cell atIndexPath:indexPath];//必須先對(duì)Cell中的數(shù)據(jù)進(jìn)行配置使動(dòng)態(tài)計(jì)算時(shí)能夠知道根據(jù)Cell內(nèi)容計(jì)算出合適的高度
    
    /*------------------------------重點(diǎn)這里必須加上contentView的寬度約束不然計(jì)算出來的高度不準(zhǔn)確-------------------------------------*/
    CGFloat contentViewWidth = CGRectGetWidth(self.tableView.bounds);
    NSLayoutConstraint *widthFenceConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:contentViewWidth];
    [cell.contentView addConstraint:widthFenceConstraint];
    // Auto layout engine does its math
    CGFloat fittingHeight = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    [cell.contentView removeConstraint:widthFenceConstraint];
    /*-------------------------------End------------------------------------*/
    
    return fittingHeight+2*1/[UIScreen mainScreen].scale;//必須加上上下分割線的高度
}


#pragma mark Configure Cell Data
- (void)configureCell:(ZHCalculateTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    cell.model = [dataArray objectAtIndex:indexPath.row];//Cell中對(duì)其進(jìn)行處理
}

ZHCalculateTableViewCell Model的Set函數(shù)重寫為

#pragma mark - Setters
-(void)setModel:(ZHCalculateHeightModel *)model
{
    _model = model;
    self.TitleLabel.text = model.title;
    self.ContentLabel.text = model.content;
    self.showImgView.image = model.imageName.length > 0 ? [UIImage imageNamed:model.imageName] : nil;
    self.UseNameLabel.text = model.username;
    self.TimeLabel.text = model.time;
    
}

擴(kuò)展

我們可以在計(jì)算高度后對(duì)其進(jìn)行緩存,下次可以直接返回!如何緩存可以看為UITableViewCell 高度自適應(yīng)加速.

總結(jié)

  • -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath一定不要用ZHCalculateTableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];來獲取Cell。這里是因?yàn)?code>[tableView cellForRowAtIndexPath:indexPath]會(huì)調(diào)用-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath導(dǎo)致進(jìn)入死循環(huán)。
  • 上述動(dòng)態(tài)計(jì)算Cell高度中最最重要的是需要在計(jì)算前先初始化Cell中的數(shù)據(jù)。
  • 一定要對(duì)ContentView加上寬度約束。
 CGFloat contentViewWidth = CGRectGetWidth(self.tableView.bounds);
    NSLayoutConstraint *widthFenceConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:contentViewWidth];
    [cell.contentView addConstraint:widthFenceConstraint];
    // Auto layout engine does its math
    CGFloat fittingHeight = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    [cell.contentView removeConstraint:widthFenceConstraint];

Demo 下載地址

GitHub

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容