轉(zhuǎn)載文章占键,純粹為知識(shí)分享
我們開(kāi)發(fā)中,在使用UITableView的時(shí)候經(jīng)常會(huì)遇到這樣的需求:table view的cell中的內(nèi)容是動(dòng)態(tài)的君仆。于是我們就在table view的代理中手動(dòng)去計(jì)算cell中的內(nèi)容高度牲距。這樣做有兩個(gè)問(wèn)題:
計(jì)算代碼冗長(zhǎng)、復(fù)雜咖摹。
每次 reload tableview 的時(shí)候难述,系統(tǒng)會(huì)先計(jì)算出每一個(gè) cell 的高度吐句,等所有高度計(jì)算完畢店读,確定了 tableview 的contentSize后,才開(kāi)始渲染視圖并顯示在屏幕上文虏。如果數(shù)據(jù)比較多殖演,就會(huì)感受到非常明顯的卡頓。
所以趴久,我們應(yīng)該尋找其他的解決方案。如果你的項(xiàng)目只支持iOS8及以上,那么恭喜你滥酥,你只用簡(jiǎn)單的幾步就可以實(shí)現(xiàn)自適應(yīng)cell了畦幢。如果是iOS7也沒(méi)關(guān)系,后面我也會(huì)講到宇葱,如何在iOS下實(shí)現(xiàn)自適應(yīng)cell。
在講具體的實(shí)現(xiàn)之前诸尽,必須得說(shuō)一下iOS7中新增的一個(gè)API:
-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;
這個(gè)方法用于返回一個(gè) cell 的預(yù)估高度印颤,如果實(shí)現(xiàn)了這個(gè)代理方法,tableview 首次加載的時(shí)候就不會(huì)調(diào)用heightForRowAtIndexPath 方法际看,而是用 estimatedHeightForRowAtIndexPath 返回的預(yù)估高度計(jì)算 tableview 的contentSize矢否,然后 tableview 就可以顯示出來(lái)了,等到 cell 可見(jiàn)的時(shí)候赖欣,再去調(diào)用heightForRowAtIndexPath 獲取 cell 的正確高度。
通過(guò)實(shí)現(xiàn)這個(gè)代理方法畏鼓,解決了首次加載 table view 出現(xiàn)的性能問(wèn)題,但是并沒(méi)有讓我們從復(fù)雜的計(jì)算中解脫出來(lái)膳沽。下面我會(huì)通過(guò)例子來(lái)講解一下在iOS7和iOS8中自適應(yīng)cell的實(shí)現(xiàn)让禀。
iOS8的自適應(yīng)cell
要想讓table view的cell自適應(yīng),有幾個(gè)要點(diǎn):
設(shè)置的AutoLayout約束必須讓 cell 的contentView知道如何自動(dòng)伸展痛阻。關(guān)鍵點(diǎn)是contentView的 4 個(gè)邊都要設(shè)置連接到內(nèi)容的約束腮敌,并且內(nèi)容是會(huì)動(dòng)態(tài)改變尺寸的。其實(shí)只要記住弊添,我們?cè)谠O(shè)置約束時(shí)只要能讓contentView能被內(nèi)容撐起來(lái)就可以了捌木。
UITableView 的rowHeight的值要設(shè)置為UITableViewAutomaticDimension。
和 iOS 7 一樣刨裆,可以實(shí)現(xiàn) estimatedHeightForRowAtIndexPath 代理方法提升 table view 的第一次加載速度。也可以直接這樣:self.tableView.estimatedRowHeight =? 60瞬女。
好了咱們來(lái)直接上代碼:
在 Xcode 中新建一個(gè)項(xiàng)目努潘,設(shè)置好tableView后,自定義一個(gè)UITableViewCell:
屏幕快照 2016-02-24 上午10.25.12.png
創(chuàng)建好之后是這樣的:
屏幕快照 2016-02-24 上午10.35.26.png
下面來(lái)看一下約束,這個(gè)是決定你的cell能否自適應(yīng)的關(guān)鍵贴膘。
UIImageView約束如下:
左邊距離contentView左邊15
頂部距離contentView頂部8
width和height為 40
底部距離contentView底部大于或等于0(為了防止文本內(nèi)容太少,導(dǎo)致 cell 高度小于圖片高度)
UILabel有四個(gè)約束:
左邊距離圖片8
右邊距離contentView右邊15
頂部距離contentView頂部8
底部距離contentView底部4
不要忘了將UILabel的numberOfLines設(shè)為0
以上約束就可以將contentView撐起來(lái)了洋闽。
控制器中代碼如下:
- (void)viewDidLoad {? ? [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.self.tableView.estimatedRowHeight =60;self.tableView.rowHeight =UITableViewAutomaticDimension;? ? [self.tableView registerNib:[Cell1 nib] forCellReuseIdentifier:[Cell1 identifier]];}
- (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {? ? Cell1 *cell1 = [tableViewdequeueReusableCellWithIdentifier:[Cell1 identifier]forIndexPath:indexPath];? ? cell1.textLab.text = self.data[indexPath.row];returncell1;}
決定cell自適應(yīng)內(nèi)容的也就這兩行代碼:self.tableView.rowHeight = UITableViewAutomaticDimension; self.tableView.estimatedRowHeight = 60;
看一下效果:
屏幕快照 2016-02-24 上午10.49.42.png
iOS7的自適應(yīng)cell
iOS7相比iOS8實(shí)現(xiàn)起來(lái)代碼多一點(diǎn)但是并不復(fù)雜诫舅,還是用上個(gè)例子中的cell,
我們?cè)趆eightForRowAtIndexPath中計(jì)算高度:
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {NSString*identifier = [Cell1 identifier];? ? Cell1 *cell1 =self.offScreenCells[identifier];if(!cell1) {? ? ? ? cell1 = [[[NSBundlemainBundle] loadNibNamed:@"Cell1"owner:niloptions:nil] lastObject];self.offScreenCells[identifier] = cell1;? ? }? ? cell1.textLab.text =self.data[indexPath.row];? ? [cell1 setNeedsUpdateConstraints];? ? [cell1 updateConstraintsIfNeeded];CGFloatheight = [cell1.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;returnheight +1;}
這里主要使用systemLayoutSizeFittingSize:來(lái)獲取內(nèi)容的高度,所以在獲取高度之前我們必須有一個(gè)實(shí)例化的cell这弧。我在這里使用字典存儲(chǔ)cell虚汛,主要是因?yàn)橐粋€(gè)tableView中可能有多種不同的cell。獲取到cell之后將內(nèi)容添加上去蛋辈,然后更新約束将谊。
屏幕快照 2016-02-24 上午11.27.10.png
要想實(shí)現(xiàn)上圖效果還有一個(gè)需要注意的地方,那就是要給顯示label的preferredMaxLayoutWidth賦一個(gè)值:
- (void)awakeFromNib {// Initialization codeself.textLab.preferredMaxLayoutWidth =250;}
也可以在給label設(shè)置約束時(shí)直接將width定死逞频,而不是通過(guò)距離contentView右邊間距來(lái)確定寬度眠砾。
以上就是在iOS7及以上版本中實(shí)現(xiàn)自適應(yīng)cell的方法托酸,如果有什么錯(cuò)誤,希望大家能指正励堡。你們的支持將是我寫作的最大動(dòng)力应结。
貼一下demo地址:iOS7和iOS8下的自適應(yīng)cell