標籤:
- 要實現的效果
- 要求:
- storyboard上的準備工作
- 建好cell自訂AutoCell 類,關聯好控制項,事先準備好一些資料來源
- 實現tableview的委託方法
- 核心部分,HeightForRow方法實現
- 具體的計算高度方法是現在自訂cell類中
- 幾大需要注意的地方
- 在ios6.0上測試
要實現的效果要求:
一般titleLabel 僅顯示一列名,高度為固定。
imageview 大小也為固定。
detailLabel 寬度固定,但高度根據文本動態調整。
cell 底部拒imageview 的底部以及detailLabel 底部高度都是大於等於20。
當detailLabel文字很少時,cell底部拒imageview底部維持20,這時detaillabel底部距cell 底部大於20.
當detailLabel文字很多時,cell底部距imageview底部超過20,與detailLabel底部高度維持20.
storyboard上的準備工作
注意將detailLabel numberOfLines 設為0
建好cell自訂AutoCell 類,關聯好控制項,事先準備好一些資料來源?
| 123 |
nameArray = [NSMutableArray arrayWithObjects:@"蝸殼",@"AI",@"大詹皇",nil]; imageArray = [NSMutableArray arrayWithObjects:@"u=4040080498,3072784853&fm=90&gp=0.jpg",@"u=2384677404,2895132414&fm=21&gp=0.jpg",@"u=262781505,2408318453&fm=21&gp=0.jpg", nil]; descriptionArray = [NSMutableArray arrayWithObjects:@"蝸殼打球好瀟洒,好飄逸,鐵王之王",@"AI,史上最矮狀元,無冕之王,crossover簡直厲害,觀賞性強,永遠的MVP!!!!",@"最年輕的一萬分先生,MVP,奧布萊恩杯,效率之王,天之驕子,全宇宙最強的球員沒有之一,強突暴扣身體棒,髮際線又高了,關鍵時刻又聳了,帶領騎士奪冠吧,雖然看起來還沒戲!!!!!!", nil]; |
實現tableview的委託方法?
| 1234567891011121314151617 |
//numberOfRows-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return 3;}//cellForRow-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ AutoTableViewCell *cell = (AutoTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"autoCell"]; [cell.titleLabel setText:nil]; [cell.titleLabel setText:[nameArray objectAtIndex:indexPath.row]]; [cell.descriptionLabel setText:nil]; [cell.logoImageView setImage:[UIImage imageNamed:[imageArray objectAtIndex:indexPath.row]]]; [cell.descriptionLabel setText:[descriptionArray objectAtIndex:indexPath.row]]; return cell;} |
先不實現HeightForRow方法,直接運行,發現ios7,ios8上都沒有得到想要的效果
IT‘S SO BAD!!!
核心部分,HeightForRow方法實現?
| 1234567891011121314 |
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ static AutoTableViewCell *cell = nil; static dispatch_once_t onceToken; //只會走一次 dispatch_once(&onceToken, ^{ cell = (AutoTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"autoCell"]; }); //calculate CGFloat height = [cell calulateHeightWithtTitle:[nameArray objectAtIndex:indexPath.row] desrip:[descriptionArray objectAtIndex:indexPath.row]]; return height;} |
具體的計算高度方法是現在自訂cell類中?
| 1234567891011121314 |
-(CGFloat)calulateHeightWithtTitle:(NSString*)title desrip:(NSString*)descrip{ //這裡非常重要 CGFloat preMaxWaith =[UIScreen mainScreen].bounds.size.width-108; [self.detailLabel setPreferredMaxLayoutWidth:preMaxWaith]; [self.titleLabel setText:title]; //這也很重要 [self.detailLabel layoutIfNeeded]; [self.detailLabel setText:descrip]; [self.contentView layoutIfNeeded]; CGSize size = [self.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; //加1是關鍵 return size.height+1.0f;} |
幾大需要注意的地方
這是storyboard 上detailLabel 的該屬性,預設是沒有勾選的(automatic)表示系統自動計算最大布局寬度,但是查看官方文檔,你會發現自動計算只有在ios8中才會有效果,低於ios8不會自動計算。這時你可能會說:那把它勾上吧!!!
,勾上之後你發現顯示的是492,這是什麼意思?這個數字是當前使用的storyboard 的寬度減去label到兩邊界的絕對距離。xcode6 為大尺寸storyboard 寬度600 ,減去 detailLabel 距左邊界98,減去距右邊界10,剛好492.
但是這樣對嗎?很明顯不對,iphone 螢幕寬度不是已經有3種寬度了嗎?320、375(iphone6)、414(plus)
所以600很明顯不對,應該用當前啟動並執行寬度來減去108,所以這裡勾不勾都是錯,乾脆不勾了直接代碼算吧....
?
| 1 |
CGFloat preMaxWaith =[UIScreen mainScreen].bounds.size.width-108; |
?
| 12 |
[self.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];return size.height+1.0f; |
這裡size.height 實際上是我們要的contentview 的高度,但是我們如果直接將這個高度返回,就賦給了cell的高度,但是由於cell 分界線的原因,cell的高度比contentview高度多1,所以這裡加1再返回。不要小看1像素,少了它效果還真就出不來!!!!
注意了這些,我們再運行,發現得到了想要的效果,切換模擬器,也沒問題。
在ios6.0上測試
沒有6.0的模擬器了,找了台6.0的真機,測試後效果
detailLabel的高度始終沒有改變,維持在一行,但是可以發現cell的高度是對的,這似乎說明heightforrow方法沒問題,那detailLabel為何沒有自動展開呢?
再次檢查了代碼,原來問題出在cellforrow方法中,因為每個cell上的detailLabel的高度要展開就應該給每個detailLabel設定最大布局寬度:preferredMaxLayoutWidth。之前做的僅僅只是在heightforrow裡面的得到那個用來計算的cell設定過。所以加了幾句代碼
?
| 12345678910111213141516 |
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ AutoTableViewCell *cell = (AutoTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"autoCell"]; [cell.titleLabel setText:nil]; [cell.titleLabel setText:[nameArray objectAtIndex:indexPath.row]]; //補上的幾句,給用來顯示的DetailLabel 設定最大布局寬度 CGFloat preMaxWaith =[UIScreen mainScreen].bounds.size.width-108; [cell.detailLabel setPreferredMaxLayoutWidth:preMaxWaith]; [cell.detailLabel layoutIfNeeded]; [cell.detailLabel setText:nil]; [cell.logoImageView setImage:[UIImage imageNamed:[imageArray objectAtIndex:indexPath.row]]]; [cell.detailLabel setText:[descriptionArray objectAtIndex:indexPath.row]]; return cell;} |
再次運行,可以看到在ios6中也得到了想要的效果,
IT‘S perfect!!!
總之,研究了幾天布局,發現ios好坑,各種陷阱,好在查閱了中外各種資料,最終還是實現了效果。
項目源碼:https://github.com/zhangxh6931/AutolayoutCell
IOS 6.0+ Autolayout — UITableViewCell 高度調整