--關(guān)于在storyboard中使用靜態(tài)TableViewCell的可變高度的使用技巧
起因:在storyboard使用之前掐暮,創(chuàng)建tableView視圖,通常是采用代碼控制數(shù)據(jù)源略贮,通過(guò)數(shù)據(jù)源數(shù)據(jù)的長(zhǎng)度來(lái)決定tableView中cell的個(gè)數(shù)记罚,而這樣做的好處還有就是可以通過(guò)將已經(jīng)在界面中展示的cell放入緩存池中验毡,以供后續(xù)數(shù)據(jù)展示再?gòu)木彺娉刂腥〕鲞M(jìn)行復(fù)用。這樣做的好處是為了防止數(shù)據(jù)過(guò)大時(shí)創(chuàng)建大量的cell浪費(fèi)不必要的空間阅酪。顯而易見(jiàn)西设,tableView就是為了進(jìn)行批量數(shù)據(jù)的展示棍鳖。
然而炮叶,在現(xiàn)實(shí)開(kāi)發(fā)中,會(huì)出現(xiàn)一種需求:展示的數(shù)據(jù)長(zhǎng)度是確定的渡处,而且需要向tableView一樣實(shí)現(xiàn)視圖上下滾動(dòng)镜悉,單個(gè)cell視圖可點(diǎn)擊響應(yīng)。這種情況下医瘫,繼續(xù)使用原來(lái)的代碼數(shù)據(jù)源控制一樣可以實(shí)現(xiàn)侣肄,這時(shí)的數(shù)據(jù)源個(gè)數(shù)是確定的。即便如此登下,你也需要考慮處理cell滾動(dòng)時(shí)發(fā)生的重用所帶來(lái)的影響茫孔。而且當(dāng)數(shù)據(jù)源確定時(shí),你的產(chǎn)品經(jīng)理絕對(duì)不甘于像平常一樣每條數(shù)據(jù)都展示為同一個(gè)尺寸內(nèi)容被芳。而是會(huì)盡可能地在每個(gè)cell中加入豐富的控件缰贝,時(shí)間相應(yīng)來(lái)是有限的tableView實(shí)現(xiàn)最為復(fù)雜的用戶(hù)交互事件。此時(shí)畔濒,你會(huì)在自己的數(shù)據(jù)源拼命地書(shū)寫(xiě)if語(yǔ)句來(lái)保證視圖的正確顯示剩晴,又要避免發(fā)生未知的cell重用問(wèn)題。
這樣做是可行的,但是在主要時(shí)間將大量花費(fèi)在處理有限個(gè)數(shù)cell上的邏輯處理赞弥,而并非我們所要實(shí)現(xiàn)的主要業(yè)務(wù)毅整。
所以,在這種情況下绽左,我們會(huì)考慮把這些重復(fù)而且無(wú)用的邏輯處理交給蘋(píng)果自己搞定(當(dāng)然悼嫉,主要目的是為了偷懶_)
static cell,這是蘋(píng)果為我們提供的解決方案拼窥。目前僅限于在storyboard中使用戏蔑。
static cell
的用法非常簡(jiǎn)單,這里不作為重點(diǎn)贅述鲁纠,請(qǐng)大家自行學(xué)習(xí)总棵。
現(xiàn)在給大家這樣一個(gè)場(chǎng)景,在你用static cell
搭建好界面改含,然后輕松加愉快的拖拖控件情龄,完成相關(guān)業(yè)務(wù)功能。
上面老板開(kāi)始驗(yàn)收項(xiàng)目捍壤,對(duì)產(chǎn)品 說(shuō)你的界面不夠詳細(xì)骤视,再改改。
產(chǎn)品開(kāi)始提需求鹃觉,說(shuō)我們的cell內(nèi)容太少尚胞,需要在點(diǎn)擊時(shí)展開(kāi)詳情。
而恰好你用靜態(tài)單元cell偷了個(gè)懶帜慢,現(xiàn)在要為了一個(gè)cell重新用動(dòng)態(tài)cell寫(xiě)一遍?
別鬧了唯卖,明天還要和UI妹子去爬香山呢粱玲,絕壁不當(dāng)加班狗。
所以拜轨,我們開(kāi)始探索靜態(tài)cell的高度改變之旅抽减。
方案一:
既然我們可以將靜態(tài)cell當(dāng)做一個(gè)控件拖入控制器做屬性。何不在代碼中修改作為屬性的靜態(tài)cell的高度呢橄碾?
self.fuJianCell.height = 100;
[self.fuJianCell layoutIfNeeded];
[self.tableView reloadData];
然并卵卵沉,這些方法對(duì)非cell的控件來(lái)說(shuō)刷新高度足矣,然而tableView
的高度始終是由代理來(lái)控制的法牲,所以這樣修改是沒(méi)用的史汗。
既然這樣,我們就從高度代理入手拒垃。
方案二:
通過(guò)代理入手停撞,將每個(gè)cell的在storyBoard的設(shè)置高度用代碼寫(xiě)到一個(gè)數(shù)組中,并通過(guò)代理返回。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 變高行數(shù)
NSInteger mutableHeightRow = 1;
// 如果不展開(kāi)
if(!isOpen){
self.heights[mutableHeightRow] = @(原始高度);
return [self.heights[indexPath.row] integerValue];
} else {
self.heights[mutableHeightRow] = @(展開(kāi)高度);
return [self.heights[indexPath.row] integerValue];
}
}
問(wèn)題解決戈毒,但是違背了我們的初衷艰猬,說(shuō)好的交給蘋(píng)果自己算呢,為毛要手動(dòng)將高度存在數(shù)組中埋市?
方案三:
交給tableView的父類(lèi)方法返回我們?cè)趕toryboard中預(yù)設(shè)的高度冠桃,然后單獨(dú)處理變高的cell高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 變高行數(shù)
NSInteger mutableHeightRow = 1;
if (indexPath.row == mutableHeightRow) {
if (!isOpen) {
// 假設(shè)改行原來(lái)高度為200
return 80;
} else {
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
} else {
/** 返回靜態(tài)單元格故事板中的高度 */
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
}
完美~
// 注意別忘了,在修改展開(kāi)狀態(tài)的時(shí)候刷新表格
isOpen = YES;
[self.tableView reloadData];
其實(shí),這樣處理靜態(tài)cell的方式不光可以處理可變高度道宅,還可以用在數(shù)據(jù)源的section個(gè)數(shù)或者每個(gè)section的row的個(gè)數(shù)上食听,再或者指定讓某個(gè)位置的cell使用動(dòng)態(tài)cell其他使用靜態(tài)cell,讓我們的靜態(tài)cell比動(dòng)態(tài)cell更好用培己。其方法都是通過(guò)super
關(guān)鍵字調(diào)用父類(lèi)方法返回storyboard中存儲(chǔ)的的相關(guān)數(shù)據(jù)碳蛋。
至于原理,暫時(shí)還不清楚省咨,推測(cè)使用了運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建一個(gè)支持靜態(tài)cell的tableView的子類(lèi)肃弟,我們實(shí)際使用的是這個(gè)新的tableView類(lèi)的實(shí)例,或者使用類(lèi)簇
零蓉,利用私有子類(lèi)進(jìn)行了相關(guān)的靜態(tài)cell的邏輯處理笤受。
總之,這讓我們省去了很多處理邏輯的代碼敌蜂。
參考文章:UITableView的:在處理混合cell表視圖的靜態(tài)和動(dòng)態(tài)的cell小區(qū)選擇