【Objective-c】 TableView 中Cell 的高度自適應(yīng)

在項(xiàng)目開發(fā)中,我們難免會(huì)遇到tableView的Cell的高度自適應(yīng),在這里就介紹一下經(jīng)常出現(xiàn)的三種情況

1、cell根據(jù)Label的高度而改變

有兩種方法:

方法一:可視化添加約束實(shí)現(xiàn)(即定制Cell)在storyboard和xib的原理是一樣的,這里以storyboard為例

要根據(jù)Label 的內(nèi)容自適應(yīng)Cell的高度,那么就必須固定寬度才能計(jì)算高度,這里通過添加Label兩邊的約束,根據(jù)屏幕的大小來固定寬度的。

寬度固定了,那么再給Label添加上下約束,如上圖,這樣系統(tǒng)就可以根據(jù)上下約束的值和Label的高度計(jì)算得出Cell的高度了,這里要注意的有兩點(diǎn):1.Label的行數(shù)要設(shè)置為0,才能自動(dòng)換行。2.因?yàn)镃ell的高度是根據(jù)zongse框Label的高度計(jì)算高度,使用只能給Label添加上下約束,而“內(nèi)容”的label是不能添加約束的,不然就沖突了

當(dāng)然定制好Cell之后,還需添加一句代碼

_tableView.rowHeight=UITableViewAutomaticDimension;//自動(dòng)換行(iOS8.0之后是默認(rèn)值,不用再設(shè)置)
_tableView.estimatedRowHeight = 100;//預(yù)設(shè)高度(注意并不是最小高度)只是為了設(shè)置contentsize

方法二:代碼實(shí)現(xiàn) ,實(shí)現(xiàn)如下圖效果

Label顯示內(nèi)容:
_dataString=@"好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)習(xí)好好學(xué)";
在tableView的HeightForRow代理方法中,動(dòng)態(tài)改變高度

- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{
   //設(shè)定字體格式
  NSDictionary*fontDt = [NSDictionarydictionaryWithObjectsAndKeys:    [UIFontsystemFontOfSize:17],NSFontAttributeName,nil];
  //設(shè)定寬度計(jì)算高度
  CGRect rect = [_dataString   boundingRectWithSize:CGSizeMake(self.view.frame.size.width-101,0)options:NSStringDrawingUsesLineFragmentOrigin attributes:fontDt context:nil];
  return rect.size.height+22+2;
  //22是Label 上下約束之和
  //2是NSStringDrawingUsesLineFragmentOrigin屬性不包括線條的寬度,所以這里需要添加上下兩條線條的寬度
}

2、Cell根據(jù)TextView輸入的內(nèi)容動(dòng)態(tài)改變高度

同樣實(shí)現(xiàn)方法也分兩種

方法一:在storyboard定制Cell中實(shí)現(xiàn)

分兩步:
第一步:設(shè)置textView的delegate的為Cell,并且在定制的Cell類中的.m 文件中實(shí)現(xiàn) textView的代理方法,代碼如下

- (void)textViewDidChange:(UITextView*)textView{
  if([self.delegaterespondsToSelector:@selector(textViewCell: didChangeText:)]) {
      [self.delegatetextViewCell:selfdidChangeText:textView.text];
  }
  CGRectbounds = textView.bounds;
  CGSizemaxSize =CGSizeMake(bounds.size.width,CGFLOAT_MAX);
  CGSizenewSize = [textViewsizeThatFits:maxSize];
  bounds.size= newSize;
  textView.bounds= bounds;
  //讓table view重新計(jì)算高度并刷新  
  UITableView*tableView = [selftableView];
  [tableViewbeginUpdates];
  [tableViewendUpdates]; 
}

- (UITableView*)tableView{
  UIView*tableView =self.superview;
  while(![tableViewisKindOfClass:[UITableViewclass]] && tableView) {
      tableView = tableView.superview;
  }
  return(UITableView*)tableView;
}

最后在VC方法中設(shè)置tableView自適應(yīng)高度就可以了,添加以下代碼

  self.tableView.estimatedRowHeight = 100;
  self.tableView.rowHeight = UITableViewAutomaticDimension;

注意:在VC中不能實(shí)現(xiàn)tableView的heightForCell代理方法,因?yàn)榍懊嬉呀?jīng)設(shè)置了是自適應(yīng)高度的,所以系統(tǒng)會(huì)自己計(jì)算


第二種:使用tableView的heightForCell代理方法實(shí)現(xiàn)(這也是會(huì)經(jīng)常用到的,一個(gè)VC中有可能存在多個(gè)tableView或多種Cell)

在cell的定制中,除了要添加textView的上下左右約束外,也是跟第一種方法一樣,在設(shè)置以下事項(xiàng)


然后在新建的Cell類中,沒有什么特殊設(shè)置代碼要添加,就跟平時(shí)一樣就可以了,該拉線就拉線
重點(diǎn)在VC中textView的delegate方法中和tableView的heightForCell方法中,廢話不多說,直接看代碼

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    NSString *heightString = [_heightRecordDt objectForKey:indexPath];
    //設(shè)置最小高度
    if (heightString.floatValue < 44) {
        return 44;
    }else{
        return heightString.floatValue;
    }
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    MyCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell"];
    cell.MyTextView.delegate = self;
    cell.MyTextView.text = [_textViewStringDt objectForKey:indexPath];
    cell.MyTextView.tag = indexPath.section*1000 + indexPath.row;
    cell.MyTextView.scrollEnabled = NO;
    return cell;
}

#pragma mark - textView delegate
- (void)textViewDidChange:(UITextView *)textView{
    NSIndexPath *index = [NSIndexPath indexPathForRow:textView.tag%1000 inSection:textView.tag/1000];
    CGRect rect1 = textView.frame;
    CGSize maxSize = CGSizeMake(rect1.size.width, CGFLOAT_MAX);
    CGSize newSize = [textView sizeThatFits:maxSize];
    rect1.size = newSize;
    textView.frame = rect1;
    
    //保存內(nèi)容,便于cell的復(fù)用
    [_textViewStringDt setObject:textView.text forKey:index];
    NSString *heightString = [_heightRecordDt objectForKey:index];
    //判斷:當(dāng)高度發(fā)生改變的時(shí)候才刷新cell
    //單獨(dú)刷新一個(gè)cell
    if (rect1.size.height != heightString.floatValue) {
        //保存最新高度
        [_heightRecordDt setObject:[NSString stringWithFormat:@"%f",rect1.size.height+12] forKey:index];
        [_tableView beginUpdates];
        [_tableView endUpdates];
    }
}

完整的github:demo
https://github.com/ZeroOnetoo/MZTableViewCell
歡迎各位碼民吐槽,集思廣益,會(huì)將最新的技術(shù)更新?。?br> 請多多點(diǎn)贊,謝謝!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容