代碼地址: demo的github下載地址?
cell高度計(jì)算的歷史
在iOS8之前株灸,如果UITableViewCell的高度是動(dòng)態(tài)的堤结,如果想要顯示正確的話芦劣,我們需要在下面這個(gè)UITableView的代理方法中鸽捻,返回每一行的精確高度:
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath;
如果cell的控件很多旧烧,樣式很復(fù)雜的話特咆,在這里面我們就可能需要寫(xiě)很多代碼去做一些復(fù)雜的計(jì)算季惩,甚至可能導(dǎo)致滑動(dòng)不流暢。
系統(tǒng)的cell自適應(yīng)高度的使用方法
首先我們需要把cell上的控件自上而下加好約束
加好約束后腻格,然后告訴tableView自己去適應(yīng)高度就可以了画拾。有兩種寫(xiě)法:
self.tableView.rowHeight= UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight=100;
或者直接代理方法:
- (CGFloat)tableView:(UITableView*)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath*)indexPath? {
????? return100;
}
這個(gè)的意思就是告訴tableView,你需要自己適應(yīng)高度菜职,我不給你算啦哈哈哈青抛。但是我們需要告訴它一個(gè)大概高度,例如上面的100酬核,理論上這個(gè)是可以隨便寫(xiě)的蜜另,并不影響顯示結(jié)果,但是越接近真實(shí)高度越好嫡意。
效果如下:
其實(shí)section的header和footer也是可以自動(dòng)適應(yīng)的举瑰,對(duì)應(yīng)的方法有:
- (CGFloat)tableView:(UITableView*)tableView estimatedHeightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView*)tableView estimatedHeightForFooterInSection:(NSInteger)section;
注意:若約束不是自上而下就會(huì)發(fā)生高度顯示不對(duì)的問(wèn)題:
點(diǎn)擊狀態(tài)欄無(wú)法滾動(dòng)到頂部
我們知道,如果界面中有UIScrollView的話蔬螟,點(diǎn)擊狀態(tài)欄會(huì)讓其滾動(dòng)到頂部此迅,就像這樣:
解決這個(gè)問(wèn)題的辦法是去緩存cell的高度,代碼如下:
@property(nonatomic,strong)NSMutableDictionary*heightAtIndexPath;//緩存高度所用字典
#pragma mark - UITableViewDelegate
-(CGFloat)tableView:(UITableView*)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath*)indexPath? {
NSNumber*height = [self.heightAtIndexPathobjectForKey:indexPath];
????? if(height)? ? ? {
?????????? returnheight.floatValue;? ?
? ? ? }else{
?????????? return100;? ?
? ? ? }?
}
- (void)tableView:(UITableView*)tableView willDisplayCell:(UITableViewCell*)cell forRowAtIndexPath:(NSIndexPath*)indexPath? {
?????? NSNumber*height = @(cell.frame.size.height);??
? ? ?? [self.heightAtIndexPathsetObject:height forKey:indexPath];
? }
解釋一下,就是用一個(gè)字典做容器耸序,在cell將要顯示的時(shí)候在字典中保存這行cell的高度忍些。然后在調(diào)用estimatedHeightForRowAtIndexPath方法時(shí),先去字典查看有沒(méi)有緩存高度佑吝,有就返回坐昙,沒(méi)有就返回一個(gè)大概高度绳匀。
緩存高度之后芋忿,在demo里面多試幾次,發(fā)現(xiàn)點(diǎn)擊狀態(tài)欄已經(jīng)可以精確滾動(dòng)回頂部了,這段代碼其實(shí)可以寫(xiě)在viewController的基類里面疾棵,這樣寫(xiě)一遍就可以每個(gè)地方都能緩存cell的高度了戈钢。詳見(jiàn)demo。這樣就完美了是尔!