iOS AutoLayout進階(五)UITableViewCell自動高度

朱曉輝Allen發表於2019-03-04

前言

前面幾個章節詳細介紹了Aspect Ratio、Content Hugging Priority(抗拉伸優先順序)和Content Compression Resistance Priority(抗壓縮優先順序),
本文將綜合運用這些特性,在不計算UITableViewCell高度、不使用第三方自動計算高度框架的前提下,來實現UITableViewCell自動高度.

iOS AutoLayout進階(五)UITableViewCell自動高度

一. UITableViewCell自動高度:

iOS8 WWDC 中推出了 self-sizing cell 的概念,旨在讓 cell 自己負責自己的高度計算,
由於之前APP 需要相容iOS7,所以很多開發者由於考慮到相容iOS7,還是使用手動計算高度,或第三方自動計算高度框架,來計算動態UITableViewCell高度,
但隨著Xcode9普及,開發工具限制了最低只能相容到iOS8,所以我們可以好好運用這一特性了,不必在使用傳統方式來處理動態UITableViewCell高度了.

二.自動高度Demo效果(此效果模仿悟空問答某一介面)

Demo.gif

三.實現部分

1.UITableView只需要做如下設定
  • 如下:
//cell預估高度,設一個接近cell高度的值
self.tableView.estimatedRowHeight = 100;//也可以省略不設定,

//設定rowHeight為UITableViewAutomaticDimension,
self.tableView.rowHeight = UITableViewAutomaticDimension;//可以省略不設定
複製程式碼
  • 不實現UITableView返回cell高度代理方法
/**
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
//不實現
}
*/
複製程式碼
2. AutoLayout部分
  • cell AutoLayout部分新增好各控制元件約束,並設定好動態高度控制元件的Content Hugging Priority和Content Compression Resistance Priority優先順序即可

四.實際運用

下面我們一起來看下,在不計算高度的前提下,怎麼實現上面悟空問答介面效果

1.程式碼部分

程式碼部分很簡單,就一個簡單的UITableView,自定義一個cell,如下:

#import "ViewController.h"
#import "DemoModel.h"
#import "YYModel.h"
#import "DemoCell.h"

static NSString *const id_DemoCell = @"DemoCell";

@interface ViewController ()<UITableViewDataSource,UITableViewDelegate>
@property (nonatomic, strong) NSArray *dataArray;
@property (nonatomic, strong) UITableView *tableView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.tableView];
    [self.tableView registerNib:[UINib nibWithNibName:id_DemoCell bundle:nil] forCellReuseIdentifier:id_DemoCell];
}

#pragma mark - tableView
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.dataArray.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    DemoCell *cell = [tableView dequeueReusableCellWithIdentifier:id_DemoCell];
    if (!cell) {
        cell = [[DemoCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:id_DemoCell];
    }
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    DemoModel *model = self.dataArray[indexPath.row];
    cell.model = model;
    return cell;
}

#pragma mark - lazy
-(UITableView *)tableView{
    if(!_tableView){
        _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) style:UITableViewStylePlain];
        _tableView.delegate = self;
        _tableView.dataSource = self;
        _tableView.estimatedRowHeight = 250;//預估高度
        _tableView.rowHeight = UITableViewAutomaticDimension;
    }
    return _tableView;
}

 /** 從檔案載入資料 */
-(NSArray *)dataArray{
    if(!_dataArray){
        NSString *path = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"json"];
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] options:0 error:nil];
        _dataArray = [NSArray yy_modelArrayWithClass:[DemoModel class] json:json[@"data"]];
    }
    return _dataArray;
}

@end

複製程式碼
2.UITableViewCell AutoLayout部分
  • 新建一個cell命名DemoCell,新增子控制元件如圖

    DemoCell@2x.png
  • 並脫線生成如下變數


@property (weak, nonatomic) IBOutlet UIImageView *iconView;//影像
@property (weak, nonatomic) IBOutlet UILabel *nameLab;//名字
@property (weak, nonatomic) IBOutlet UILabel *timeLab;//時間
@property (weak, nonatomic) IBOutlet UILabel *titleLab;//標題
@property (weak, nonatomic) IBOutlet UILabel *contentLab;//內容
@property (weak, nonatomic) IBOutlet UILabel *commentLab;//評論數
@property (weak, nonatomic) IBOutlet UILabel *praiseLab;//點贊數

複製程式碼
  • 並新增如下約束
影像-iconView約束:上15,左15,高30,寬高比1:1 
名字-nameLab約束:上下均對其iconView,左5, 並設定橫向抗壓縮優先順序為749即Content Compression Resistance Priority - Horizontal:749
時間-timeLab約束:上下均對齊iconView,左5, 並設定橫向抗拉伸優先順序為250即Content Hugging Priority - Horizontal:250
關注按鈕約束:上下均對齊iconView,右15,寬度50,左5
標題-timeLab約束:左15,上15,右15,
內容-contentLab約束:左15,上15,右15,並設定並設定縱向抗拉伸優先順序為250即Content Hugging Priority - Vertical:250
三張圖約束:上15,左15,右15,中間間隙5,高度65,並設定三張圖等寬,
評論數-commentLab約束:上15,左15,下15,
點贊數-praiseLab約束:上下對齊commentLab,左5,右邊15,並設定橫向抗拉伸優先順序為250即Content Hugging Priority - Horizontal:250
複製程式碼
3.UITableViewCell控制元件賦值部分
-(void)setModel:(DemoModel *)model{
    _model = model;
    
    [_iconView sd_setImageWithURL:[NSURL URLWithString:model.icon]];
    _nameLab.text = model.name;
    _timeLab.text = model.update_time;
    _contentLab.text = model.brief;
    _titleLab.text = model.title;
    _commentLab.text = [NSString stringWithFormat:@"%ld評論",model.comment];
    _praiseLab.text = [NSString stringWithFormat:@"%ld贊",model.praise];
    
    for (int i = 0; i<3; i++) {
        UIImageView *imgView = [self viewWithTag:10+i];
        imgView.image = nil;
    }
    for (int i = 0; i<model.images.count; i++) {
        UIImageView *imgView = [self viewWithTag:10+i];
        [imgView sd_setImageWithURL:[NSURL URLWithString:model.images[i]]];
    }
}
複製程式碼
  • 到此,我們已經完成上圖demo效果,是不是很簡單,沒有寫任何高度計算的程式碼.

五.關於組頭、組尾

  • UITableView 的組頭和組尾,也可以實現自動高度,設定方法如下:

 _tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
_tableView.estimatedSectionHeaderHeight = 100;//組頭預估高度
        
_tableView.sectionFooterHeight = UITableViewAutomaticDimension;
 _tableView.estimatedSectionFooterHeight = 100;//組尾預估高度

複製程式碼
  • 並且不實現下面兩個組頭,組尾高度代理方法
/**
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
    //不實現
}
 */

/**
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    //不實現
}
 */
複製程式碼

六.關於動態高度,和固定高度混用

  • 此場景通常出現在,一個TableView有多種樣式的cell情況下,
  • 例如:組0的cell是固定高度,其他組的cell是動態高度,要怎麼設定呢?
  • 方法如下:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

    if(indexPath.section==0){
        return 100;//固定高度
    }else{
        return UITableViewAutomaticDimension;//動態高度
    }
}
複製程式碼

七.小結

  • 1.UITableViewCell動態高度,程式碼設定部分很簡單不難,主要是AutoLayout部分,要想使用起來,得心應手,開發者除了要掌握普通AutoLayout約束外,還必須熟練掌握Content Hugging Priority(抗拉伸優先順序)和Content Compression Resistance Priority(抗壓縮優先順序)的用法.
  • 2.熟練使用UITableView cell、組頭、組尾自動高度,能給我開發節省大量的時間.
  • 3.如對Content Hugging Priority(抗拉伸優先順序)和Content Compression Resistance Priority(抗壓縮優先順序)的用法不熟練的同學,可以看我前面文章:AutoLayout進階(二)、 AutoLayout進階(三)、AutoLayout進階(四),有詳細介紹兩個優先順序的用法.

程式碼地址:github.com/CoderZhuXH/…

相關文章