UITableView自動計算cell高度並緩存(Xib)

 

這篇文章咱們來說一下UITableView的cell自適應高度,以及遇到的問題的解決辦法。在看文章以前但願你已經會UITableView的基本使用了。php

先奉上這篇文章的demo的Github地址:UITableViewCellHeightDemo。你們能夠下載下來和文章配合看。ios

cell高度計算的歷史

在iOS8以前,若是UITableViewCell的高度是動態的,若是想要顯示正確的話,咱們須要在下面這個UITableView的代理方法中,返回每一行的精確高度:git

1github

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;緩存

 

若是cell的控件不少,樣式很複雜的話,在這裏面咱們就可能須要寫不少代碼去作一些複雜的計算,甚至可能致使滑動不流暢。學習

後來也有一些人寫了一些第三方去解決這個問題,例如UITableView-FDTemplateLayoutCell。只要給cell自上而下加好約束,它就能夠幫咱們去算cell的高度而且能夠緩存,省去了咱們本身寫計算代碼的成本。具體能夠進連接裏面看看它的demo。atom

可是在iOS10的系統下, FDTemplateLayoutCell會卡界面,並且tableview的行數越多表現的越卡。spa

並且蘋果在iOS8以後,推出了一種超級簡單的cell動態自適應的方法,使用起來比FDTemplateLayoutCell也簡單一些,並且如今iOS10都出來了,沒有必要去支持iOS7了,因此最後我仍是選擇了用系統的辦法。這樣咱們之後就不再用寫heightForRowAtIndexPath方法了哈哈哈。.net

系統的cell自適應高度的使用方法

首先咱們須要把cell上的控件自上而下加好約束,若是對約束不熟悉的話建議看看下面這兩篇文章學習一下:
Auto Layout Tutorial in iOS 9 Part 1: Getting Started(http://www.raywenderlich.com/115440/auto-layout-tutorial-in-ios-9-part-1-getting-started-2)
[Auto Layout Tutorial in iOS 9 Part 2: Constraints代理

用xib加約束和用masonry加代碼約束都是能夠的。注意約束必定要自上而下加好,讓系統知道怎麼去計算高度。在這篇文章的demo裏面的cell加的約束是這樣的:

cell約束

加好約束後,而後告訴tableView本身去適應高度就能夠了。有兩種寫法:

1

self.tableView.rowHeight = UITableViewAutomaticDimension;self.tableView.estimatedRowHeight = 100;

 

或者直接寫這個代理方法就能夠了

1

2

3

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

{    return 100;

}

 

這個的意思就是告訴tableView,你須要本身適應高度,我不給你算啦哈哈哈。可是咱們須要告訴它一個大概高度,例如上面的100,理論上這個是能夠隨便寫的,並不影響顯示結果,可是越接近真實高度越好。

來看下demo效果:


 

咱們看到,cell已經本身適應內容算出了高度,是否是很方便呢哼哼。
具體的代碼你們能夠去demo看哦。

其實section的header和footer也是能夠自動適應的,對應的方法有:

1

2

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section;

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section;

 

可是咱們在實際開發中,通常都是根本沒有header和footer,有的話通常也是給一個固定高度。因此在這裏就不講解了,原理都同樣。

可能遇到的問題和解決辦法

1.高度不對
有時候有可能運行出來後看到cell的高度顯示的不對,就像這樣:


這個問題是由於約束沒有知足自上而下,從而系統不知道怎麼去計算。解決辦法就是去修改約束,直到知足爲止。必定要好好理解約束啊!

2.點擊狀態欄沒法滾動到頂部
咱們知道,若是界面中有UIScrollView的話,點擊狀態欄會讓其滾動到頂部,就像這樣:


 

可是若是咱們用了自動計算高度的方法,又調用了tableView的reloadData方法(例如咱們的數據有分頁的時候,加載完下一頁的數據後會去刷新tableView)。這時候就會出現問題,點擊狀態欄就有概率不能精確滾動到頂部了:


 

解決這個問題的辦法是去緩存cell的高度,代碼以下:

1

@property (nonatomic, strong) NSMutableDictionary *heightAtIndexPath;//緩存高度所用字典

1

2

3

4

5

6

7

8

9

10

11

12

#pragma mark - UITableViewDelegate-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath

{    NSNumber *height = [self.heightAtIndexPath objectForKey:indexPath];    if(height)

    {        return height.floatValue;

    }    else

    {        return 100;

    }

}

 

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

{    NSNumber *height = @(cell.frame.size.height);

    [self.heightAtIndexPath setObject:height forKey:indexPath];

}

解釋一下,就是用一個字典作容器,在cell將要顯示的時候在字典中保存這行cell的高度。而後在調用estimatedHeightForRowAtIndexPath方法時,先去字典查看有沒有緩存高度,有就返回,沒有就返回一個大概高度。

緩存高度以後,在demo裏面多試幾回,發現點擊狀態欄已經能夠精確滾動回頂部了:


 

這段代碼其實能夠寫在viewController的基類裏面,這樣寫一遍就能夠每一個地方都能緩存cell的高度了。詳見demo。這樣就完美了!

 

 

原文:http://bbs.520it.com/forum.php?mod=viewthread&tid=2794&page=&extra=#pid30294

相關文章
相關標籤/搜索