自定義不等高的cell
1.給模型增加frame數(shù)據(jù)(純代碼)
讓ViewController繼承UITableViewController,移除storyboard中的ViewController,新建一個UITableViewController讓其與ViewController建立關(guān)聯(lián)。
@interface ViewController:UITableViewController在ViewController.m文件中實現(xiàn)UITableView代理的這個方法,這個方法會返回cell的高度,所以需要在返回高度前計算出cell的高度。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
AZStatus *status=self.statuses[indexPath.row];
return status.cellHeight;
}
- 在status數(shù)據(jù)模型中計算出所有控件frame,只有模型數(shù)據(jù)知道哪些控件需要顯示,這個方法會經(jīng)常調(diào)用,考慮到性能對其進行判斷,只有當?shù)谝淮握{(diào)用時才會計算。
- (CGFloat)cellHeight
{
if (_cellHeight==0) {
CGFloat margin=10;
...
// 圖片frame
if (self.picture) {//有配圖
CGFloat picX=margin*3;
CGFloat picY=CGRectGetMaxY(self.textFrame)+margin;
CGFloat picWH=200;
self.pictureFrame=CGRectMake(picX, picY, picWH, picWH);
_cellHeight=CGRectGetMaxY(self.pictureFrame)+margin;
}else{//無配圖
_cellHeight=CGRectGetMaxY(self.textFrame)+margin;
}
}
return _cellHeight;
}
- 添加控件
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self=[super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
...
//配圖
UIImageView *pictureView=[[UIImageView alloc]init];
[self.contentView addSubview:pictureView];
self.picture1View=pictureView;
}
- 在AZStatusCell.h文件中引用模型
#import <UIKit/UIKit.h>
@class AZStatus;
@interface AZStatusCell : UITableViewCell
/*模型數(shù)據(jù)*/
@property(nonatomic,strong)AZStatus *status;
@end
- 在模型的set方法中給控件注入數(shù)據(jù),同時也可以確定frame,和在layoutSubViews中確定frame效果一致
-(void)setStatus:(AZStatus *)status
{
_status=status;
// 設置數(shù)據(jù)
...
// 配圖
if (status.picture) {
self.picture1View.hidden=NO;
self.picture1View.image=[UIImage imageNamed:status.picture];
}else{
self.picture1View.hidden=YES;
}
//設置frame
self.iconView.frame=status.iconFrame;
self.nameLabel.frame=status.nameFrame;
self.text_Label.frame=status.textFrame;
self.vipView.frame=status.vipFrame;
self.picture1View.frame=status.pictureFrame;
}
2.storyboard動態(tài)cell實現(xiàn)(iOS8以后)
- 在stroyboard的動態(tài)cell中添加所有的子控件
-
將cell中所有的子控件和AZStatusCell.m文件中的屬性建立好連線,并將圖片的約束也建立好連線
- 在status模型的set方法中,通過圖片高度的約束控制圖片顯示與隱藏,上方間隙的約束的調(diào)整來控制所有cell下方的間隙一致
-(void)setStatus:(AZStatus *)status
{
_status=status;
// 設置數(shù)據(jù)
...
// 配圖
if (status.picture) {
self.picture1View.hidden=NO;
self.picture1View.image=[UIImage imageNamed:status.picture];
self.pictureTop.constant=10;
self.pictureHeight.constant=100;
}else{
self.picture1View.hidden=YES;
self.pictureHeight.constant=0;
self.pictureTop.constant=0;
}
}
- 設置tableViewCell的真實行高和估算行高
// self-sizing(iOS8以后,兩個方法一起使用)
// 設置tableView的高度為根據(jù)設定的約束自動計算
self.tableView.rowHeight=UITableViewAutomaticDimension;
// 設置tableView的估算高度
self.tableView.estimatedRowHeight=44;
3.如果要支持iOS8之前
- 如果cell內(nèi)部有自動換行的label,需要設置preferredMaxLayoutWidth屬性
- (void)awakeFromNib
{
// 手動設置文字的最大寬度(目的是:讓label知道自己文字的最大寬度,進而能夠計算出自己的frame)
self.text_label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
}
- 設置tableView的cell估算高度
// 告訴tableView所有cell的估算高度(設置了估算高度,就可以減少tableView:heightForRowAtIndexPath:方法的調(diào)用次數(shù))
self.tableView.estimatedRowHeight = 200;
- 在代理方法中計算cell的高度
AZStatusCell *cell;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 創(chuàng)建一個臨時的cell(cell的作用:根據(jù)模型數(shù)據(jù)布局所有的子控件,進而計算出cell的高度)
if (!cell) {
cell = [tableView dequeueReusableCellWithIdentifier:ID];
}
// 設置模型數(shù)據(jù)
cell.status = self.statuses[indexPath.row];
return cell.height;
}
- (CGFloat)height
{
// 強制布局cell內(nèi)部的所有子控件(label根據(jù)文字多少計算出自己最真實的尺寸)
[self layoutIfNeeded];
// 計算cell的高度
if (self.status.picture) {
return CGRectGetMaxY(self.pictureImageView.frame) + 10;
} else {
return CGRectGetMaxY(self.text_label.frame) + 10;
}
}