轉自:http://hi.baidu.com/vim888/blog/item/6fcd6824c091c931d507421b.html
轉載說明:領悟這篇文章的精華就好,不必將文中的方案生搬硬套.
----------------------------------------------------以下為轉自內容-----------------------------------------------------
往往在開發iPhone的應用過程中用得最多的應該算是UITableVIew了,憑着IOS給UITableView賦予了這種靈活的框架結構,讓它不管在顯示列表方面還是在排版方面都有着一定的優勢。雖然UITableView功能強大,但是對於一些復雜的應用需求在開發的過程中會出現一些問題,如動態改變UITableView顯示的Cell高度就是其中之一
其實想要改變UITableView的Cell高度並不難,UITableView帶有一個rowHeight屬性,使用他就可以改變高度了。但是這樣的改變是把所有的Cell的高度都統一改變了。如果存在不同的內容就有不同的Cell高度,那么這時候rowHeight顯得力不從心了。不過iOS似乎考慮到了這一點,在UITableView的UITableViewDelegate委托下有一個委托方法可以動態地指定Cell的高度,其聲明如下:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
此委托方法就可以根據索引位置indexPath來控制返回的Cell高度。可能有人會認為我實現這個委托就可以實現我上面說的效果了嗎?是用到這個委托沒錯,但是使用這個委托時是會存在一些問題的,下面的內容就是要針對這些問題提出我在實際的開發工作中的處理方法,希望通過共享這些思路能夠讓童鞋們少走點彎路。
其實主要的問題是heightForRowAtIndexPath這個委托的調用時機是早於cellForRowAtIndexPath這個委托方法的(此方法在UITableViewDataSource中定義)我們都知道cellForRowAtIndexPath是用於返回UITableViewCell的方法。那么問題就在這里了,如果我cell還沒返回,那我之前怎么能夠在heightForRowAtIndexPath中得到cell的高度呢?也許有人會說:我在返回Cell之后重新刷新指定的Cell就能夠得到高度了。但其實這個實踐起來是很困難的。而還有一點要注意的是在heightForRowAtIndexPath是不能使用UITableView的cellForRowAtIndexPath:返回Cell對象的。否則會導致無限級遞歸調用引發的堆棧溢出 。原因是調用此方法會觸發heightForRowAtIndexPath委托方法。但是要調用也是可以的。解決方法就是先把delegate為空,等獲取到Cell后再重新賦值。如:
tableView.delegate=nil;
UITableViewCell *cell=[tableView cellForRowAtIndexPath:indexPath];
tableView.delegate=self;
那么有什么辦法可以更加方便實現呢? 我們傳統的做法都是在 cellForRowAtIndexPat中排版或者繼承UITableViewCell進行排版。而這個也不可避免,但是對於這種動態變更高度的處理,本人認為最好不要直接在cellForRowAtIndexPat中進行排版,應該繼承UITableViewCell生成子類,然后在子類里面進行排版工作。因為這跟下面說的解決方法有關。
先說說本人的解決思路吧,其實辦法很簡單,通過樣本Cell來計算高度即可。也就是說我在定義Cell的子類后,在包含UITableView的控制器類或者視圖類中定義一個Cell子類的屬性,此屬性就是專門用於在heightForRowAtIndexPath中計算Cell高度用。這樣就能夠正確地返回Cell的高度了。先來看看Cell的子類定義:
@interface DemoCell : NSObject{
UILabel *_content;
}
-(CGFloat)contentHeight;
-(void)setContent:(NSString *)content;
@end;
從上面的DemoCell來看其帶有一個UILabel對象,這個Cell就是要根據UILabel的內容動態更改高度。其中contentHeight方法是返回Cell的高度。setContent是設置UILabel的內容並計算UILabel的高度。此類很簡單要做的就是這樣這些操作。然后我們在控制器中定義一個樣本Cell專門用於計算Cell的高度。代碼如下:
#import "DemoCell.h"
@interface DemoViewController : UIViewController<UITableViewDelegate,UITableViewDataSource>{
UITableView *_tableView;
DemoCell *_sampleCell;
NSArray *_listData;
}
@end;
其中部分實現代碼如下:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
//在此使用樣本Cell計算高度。
NSString *content=[_listData objectAtIndex:indexPath.row];
[_sampleCell setContent:content];
return [_sampleCell contentHeight];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellId=@"DemoCell";
DemoCell *cell=(DemoCell *)[tableView dequeueReusableCellWithIdentifier:cellId];
if(cell==nil){
cell=[[[DemoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId] autorelease];
}
[cell setContent:[_listData objectAtIndex indexPath:indexPath.row]];
return cell;
}
到此為止我們已經順利地展示了如何動態變更Cell的高度。只要內容變更我們調用UITableView的reloadData方法就可以刷新整個列表了。Cell如何計算高度本人沒有列出來,因為不同的需求導致這部分的實現會不一樣。這里只是把思路給大家交代清楚。具體的實現還是要各位童鞋們自己動手操作。