這篇文章咱們來說一下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 |