關于使用autolayout建立動态cell,網上也有不少的文章,但是裡面的内容都是說的一個問題,簡稱換湯不換藥,都是說的一些UILabel或者UITextView等等一些控件顯示的文本内容不同來實作不同的高度。
但是我們平常使用的自定義cell很多都是顯示不同數量的控件,來顯示不同的高度,比如微網誌首頁,餓了麼首頁那些cell,都是下面顯示不同數量的控件來顯示不同高度的cell,那麼下面就讓我們一起看看怎麼使用autolayout實作這種自定義cell
關于使用autolayout實作cell動态高度有兩種實作方式
iOS8以後
iOS8以後比較爽:隻需要設定下面兩句代碼就行了
//設定cell的估計高度
self.tableView.estimatedRowHeight = ;
//iOS以後這句話是預設的,是以可以省略這句話
self.tableView.rowHeight = UITableViewAutomaticDimension;
你可能沒有看到實作代理方法傳回cell高度。明确告訴你iOS8以後不需要實作了,系統會自動推斷出cell的高度。
but,iOS7還是需要
下面就是iOS7實作的方式,還是需要實作這個方法,iOS8那兩句代碼不寫也可以
//如果要支援iOS7這個方法必須實作
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
//其他代碼
//自動算高度,+1的原因是因為contentView的高度要比cell的高度小1
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + ;
return height;
}
主要就是下面這句代碼,能自動計算出contentView的高度和寬度
上面這兩種方式可以一起存在,既支援ios7也支援iOS8.
開始demo
先來看一下我們最終的效果:
- 有的cell隻有一個UITextLabel,并且label會根據内容的多少來改變高度
- 有的cell下面還有一個UIButton,并且cell會根據有沒有button來動态改變高度
實作思路
- 首先自定義一個cell,順便建立一個xib檔案
- 在xib檔案中把所有包含的控件全部搞上去,設定好限制
- 如果不需要哪個控件顯示就把哪個控件的高限制設定為0
- 如果需要顯示哪個控件就保證這個控件沒有高度限制(應該容易想的到因為是動态高度的cell,是以不能有高度的限制)
- 然後更新限制,顯示cell
在這裡我們使用xib的方式建立自定義cell
如圖:
這裡設定限制有幾個注意點
- 每一個控件都隻設定上下左右的限制,不設定寬高的限制,有些必須要固定大小的可以設定一下
- 有些控件如果不設定寬高xib會報錯的話,就設定占位符placehoder
- 像一些要消失或者顯示的控件,最好設定他與其他顯示的控件間距為0
這是我自定義cell的類
在控制器中我們實作資料源代碼
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:@"MyTableViewCell" bundle:nil] forCellReuseIdentifier:@"cell"];
self.tableView.allowsSelection = NO;
//胡亂寫的,為了懶省事,大家湊合着看吧
self.tableData = @[@"1\n2\n3\n4\n5\n6", @"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3\n4\n5\n6", @"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3",@"1\n2\n3",@"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3",@"1\n2\n3"@"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3",@"1\n2\n3"@"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3",@"1\n2\n3"@"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3",@"1\n2\n3"@"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3",@"1\n2\n3"];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return ;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.tableData.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
cell.text = self.tableData[indexPath.row];
return cell;
}
我們先使用iOS8的方法
接下來就是去自定義cell類(MyTableView.m)中重寫-updateConstraints 方法
-(void)updateConstraints {
//remove Constraints
[self.height uninstall];
//add Constraints
[self.content mas_makeConstraints:^(MASConstraintMaker *make) {
self.height = make.height.equalTo(@60);//any number
}];
if(self.isShowView == NO) {
//change Height Constrains to be
[self.content mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.equalTo(@0);
}];
}
else {
//remove Constraints
[self.height uninstall];
}
[super updateConstraints];
}
- 如果不需要顯示就設定高度限制為0
- 如果需要顯示就把高度限制去掉
這個方法超級重要,有些view需要顯示的話,一定要把高度限制去掉,不然cell循環使用的話會出問題。
然後就是設定要顯示的text
-(void)setText:(NSString *)text {
_text=text;
self.textView.text = text;
if ([self.text isEqualToString:@"123456789012345678901234567890"]) {
self.isShowView = NO;
self.button.hidden=YES;
self.content.hidden=YES;
self.intextView.hidden=YES;
}else {
self.isShowView = YES;
self.button.hidden=NO;
self.content.hidden=NO;
self.intextView.hidden=NO;
}
}
接下來在Controller檔案中
将cellForRowAtIndexPath方法改為下面樣子
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
cell.text = self.tableData[indexPath.row];
//傳回cell之前重新重新整理限制,重新計算高度
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
return cell;
}
然後在-viewDidLoad方法中增加兩句話就行了
self.tableView.estimatedRowHeight = ;
self.tableView.rowHeight = UITableViewAutomaticDimension;
接下來是支援iOS7的
隻需要重寫代碼方法heightForRowAtIndexPath
将這個方法内容改為下面這樣:
//如果要支援iOS7這個方法必須實作
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
self.cell = (MyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"cell"];
MyTableViewCell *cell = self.cell;
cell.text = [self.tableData objectAtIndex:indexPath.row];
//這句代碼必須要有,也就是說必須要設定contentView的寬度限制。
//設定以後,contentView裡面的内容才知道什麼時候該換行了
CGFloat contentViewWidth = CGRectGetWidth(self.tableView.frame);
[cell.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(@(contentViewWidth));
}];
//重新加載限制,每次計算之前一定要重新确認一下限制
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
//自動算高度,+1的原因是因為contentView的高度要比cell的高度小1
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + ;
return height;
}
關注我的新部落格吧!
我的新部落格位址:(http://www.codertian.com)