iOS8+ UITableView自動計算cell高度並緩衝

來源:互聯網
上載者:User

標籤:atom   技術   cell高度   儲存   它的   com   不能   聯絡   comment   

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

先奉上這篇文章的demo的Github地址:UITableViewCellHeightDemo。大家可以下載下來和文章配合看。

cell高度計算的曆史

在iOS8之前,如果UITableViewCell的高度是動態,如果想要顯示正確的話,我們需要在下面這個UITableView的代理方法中,返回每一行的精確高度:

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

如果cell的控制項很多,樣式很複雜的話,在這裡面我們就可能需要寫很多代碼去做一些複雜的計算,甚至可能導致滑動不流暢。

後來也有一些人寫了一些第三方去解決這個問題,例如UITableView-FDTemplateLayoutCell。只要給cell自上而下加好約束,它就可以幫我們去算cell的高度並且可以緩衝,省去了我們自己寫計算代碼的成本。具體可以進連結裡面看看它的demo。

但是在iOS10的系統下, FDTemplateLayoutCell會卡介面,而且tableview的行數越多表現的越卡。

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

系統的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自己去適應高度就可以了。有兩種寫法:

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

或者直接寫這個代理方法就可以了

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{    return 100;}

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

來看下demo效果:


demo

我們看到,cell已經自己適應內容算出了高度,是不是很方便呢哼哼。
具體的代碼大家可以去demo看哦。

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

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

但是我們在實際開發中,一般都是根本沒有header和footer,有的話一般也是給一個固定高度。所以在這裡就不講解了,原理都一樣。

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

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


高度不對


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

2.點擊狀態列無法滾動到頂部
我們知道,如果介面中有UIScrollView的話,點擊狀態列會讓其滾動到頂部,就像這樣:


點擊狀態列會滾動到頂部

但是如果我們用了自動計算高度的方法,又調用了tableView的reloadData方法(例如我們的資料有分頁的時候,載入完下一頁的資料後會去重新整理tableView)。這時候就會出現問題,點擊狀態列就有幾率不能精確滾動到頂部了:


Untitled.gif

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

@property (nonatomic, strong) NSMutableDictionary *heightAtIndexPath;//緩衝高度所用字典
#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。這樣就完美了!



文/iOS_小松哥(簡書作者)
原文連結:http://www.jianshu.com/p/64f0e1557562
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。

iOS8+ UITableView自動計算cell高度並緩衝

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.