天天看點

UITableView使用AutoLayout動态計算cell高度

UITableView幾乎是每個app都需要用的控件,而cell高度自适應也是我們需要掌握的,當然cell上面的控件也是有多種表現形式,今天小編講解的是其中一種比較常見的:Auto Layout with UILabel in UITableViewCell。

話不多說,上教程。

首先我們建立一個Sigle View Application的項目,然後拖上一個UITableView到storyboard中,設定好代理并且設定好限制。限制這裡就不做講解了,可以到AutoLayout詳解了解一下,接着回到我們項目,我們建立一個繼承UITableViewCell的類,此處我命名為DIYTableViewCell,接着在storyboard中拖一個UITableViewCell到UITableView上,然後把這個cell關聯我們建立的DIYTableViewCell類,什麼?不會關聯?沒關系,看這裡!

UITableView使用AutoLayout動态計算cell高度

然後給cell一個複用的辨別,這裡我命名為cell

UITableView使用AutoLayout動态計算cell高度

接下來我們在cell上面放置一個label和一個UIImageView并且設定好限制,此處注意,應該把UILabel的numberOfLines屬性設定為0.

現在我們應該給ViewController加點料了,回到我們的ViewController,實作UITableView的代理方法,

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    DIYTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:iden];
    cell.titleLabel.text = [self.tbData objectAtIndex:indexPath.row];
    return cell;
}`
           
這裡有一個需要特别注意的問題,也是效率問題。UITableView是一次性計算完所有Cell的高度,如果有100個Cell,那麼

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

就會觸發100次,然後才顯示内容。不過在iOS7以後,提供了一個新方法可以避免這100次調用,它就是

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath

。要求傳回一個Cell的估計值,實作了這個方法,那隻有顯示的Cell才會觸發計算高度的protocol. 由于systemLayoutSizeFittingSize需要cell的一個執行個體才能計算,是以這兒用一個成員變量存一個Cell的實列,這樣就不需要每次計算Cell高度的時候去動态生成一個Cell執行個體,這樣即友善也高效也少用記憶體,可謂一舉三得。關于UITableViewCell的優化,可以看這裡優化UITableViewCell高度計算

接下來我們聲明一個這樣的執行個體變量:

@property (nonatomic, strong) DIYTableViewCell *cell;
           

然後執行個體化它:

self.cell = [self.tableView dequeueReusableCellWithIdentifier:iden];
           

下面是計算cell高度的代碼:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

    DIYTableViewCell *cell = (DIYTableViewCell *)self.cell;
    cell.titleLabel.text = [self.tbData objectAtIndex:indexPath.row];
    CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    NSLog(@"調用次數%ld",indexPath.row+);
    return MAX(,  + size.height) ;
}
           

可能你會覺得奇怪,為什麼需要加1呢?筆者告訴你,如果不加1,結果就是錯誤的,Cell中UILabel将顯示不正确。原因就是因為這行代碼CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];由于是在cell.contentView上調用這個方法,那麼傳回的值将是contentView的高度,UITableViewCell的高度要比它的contentView要高1,也就是它的分隔線的高度。

到這裡我們的cell自适應高度就算完成了,看看我們的運作結果吧:

UITableView使用AutoLayout動态計算cell高度

Domo源碼已經上傳,如有需要可以下載下傳AutoLayoutCell