【问题标题】:UITableViewCell with dynamic height iOS具有动态高度 iOS 的 UITableViewCell
【发布时间】:2013-09-02 20:21:06
【问题描述】:

我已经在我的应用中使用 CustomCell 实现了 TableView,

我想要我的UITableViewCell 的动态高度根据UITableViewCell 中的文本长度,

这是Customcell的快照

: 这是我的UITableView 的快照 : heightForRowAtIndexPath 的代码 sn-p

#define FONT_SIZE 14.0f
#define CELL_CONTENT_WIDTH 320.0f
#define CELL_CONTENT_MARGIN 10.0f

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
    NSString *text = [DescArr objectAtIndex:[indexPath row]];
    CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
    CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
    CGFloat height = MAX(size.height, 100.0);
    return height; 
}

正如您在第二张图片中看到的那样,单元格的高度是固定的,它不会随其文本(内容)大小而改变。

我在哪里犯错了?如何制作标签或单元格以根据其内容/文本更新其大小?

【问题讨论】:

  • 图片丢失?? :)
  • 您用于高度计算的代码 sn-p 看起来正确,您是否正确设置了表格视图的委托?也尝试记录大小:NSLog(@"Hieght: %f", height); 并查看高度是否正确。
  • 是的,我已正确连接代理,并且我的日志显示不同的高度54.0、36.0、18.0
  • CGF 浮动高度 = MAX(size.height, 100.0);应该是 100 到 55 或默认单元格高度..
  • @Sachin:您的建议在更改为 55 单元格高度后是正确的,但标签未显示在中心。当我在cellForRowAtIndexPath NSLog(@"cell.frame.size.height=%f",cell.frame.size.height); 中记录我的单元格高度时它在所有单元格中显示高度为100

标签: ios objective-c swift uitableview row-height


【解决方案1】:

要为行高和估计行高设置自动尺寸,请确保按照以下步骤制作,自动尺寸对单元格/行高布局有效。

  • 分配和实现 tableview 数据源和委托
  • 将UITableViewAutomaticDimension 分配给rowHeight 和estimatedRowHeight
  • 实现委托/数据源方法(即heightForRowAt并返回一个值UITableViewAutomaticDimension给它)

-

@IBOutlet weak var table: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Don't forget to set dataSource and delegate for table
    table.dataSource = self
    table.delegate = self

    // Set automatic dimensions for row height
    // Swift 4.2 onwards
    table.rowHeight = UITableView.automaticDimension
    table.estimatedRowHeight = UITableView.automaticDimension


    // Swift 4.1 and below
    table.rowHeight = UITableViewAutomaticDimension
    table.estimatedRowHeight = UITableViewAutomaticDimension

}



// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    // Swift 4.2 onwards
    return UITableView.automaticDimension

    // Swift 4.1 and below
    return UITableViewAutomaticDimension
}

对于 UITableviewCell 中的标签实例

  • 设置行数=0(&换行模式=截尾)
  • 设置与其父视图/单元格容器相关的所有约束(上、下、左右)。
  • 可选:设置标签的最小高度,如果你想要标签覆盖的最小垂直区域,即使没有数据。

【讨论】:

    【解决方案2】:

    试试这个,它就像一个魅力!对我来说,

    在viewDidLoad中写下这段代码,

    -(void)viewDidLoad 
    {
    [super viewDidLoad];
     self.tableView.estimatedRowHeight = 100.0; // for example. Set your average height
     self.tableView.rowHeight = UITableViewAutomaticDimension;
    }
    

    在 cellForRowAtIndexPath 中写下这段代码,

     -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
     {
      static NSString *CellIdentifier = @"Cell";
      UITableViewCell *cell = [tableView 
      dequeueReusableCellWithIdentifier:CellIdentifier];
     if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] ;
      }
        cell.textLabel.numberOfLines = 0; // Set label number of line to 0
        cell.textLabel.text=[[self.arForTable objectAtIndex:indexPath.row] valueForKey:@"menu"];
        [cell.textLabel sizeToFit]; //set size to fit 
        return cell;
     }
    

    希望这对某些人有所帮助。

    【讨论】:

      【解决方案3】:

      以下代码对我来说很好用。试试这个

      -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
      
          CGFloat lRetval = 10;
          CGSize maximumLabelSize = CGSizeMake(231, FLT_MAX);
          CGSize expectedLabelSize;
      
      
          CGFloat numberoflines = [thirdcellText length]/17.0;
      
          if (indexPath.section == 0) {
              expectedLabelSize = [firstcellText sizeWithFont:[UIFont systemFontOfSize:16.0]
                                            constrainedToSize:maximumLabelSize
                                                lineBreakMode:NSLineBreakByWordWrapping];
              lRetval = expectedLabelSize.height;
          }
          else if(indexPath.section == 1)
          {
              expectedLabelSize = [secondcellText sizeWithFont:[UIFont systemFontOfSize:16.0]
                                             constrainedToSize:maximumLabelSize
                                                 lineBreakMode:NSLineBreakByWordWrapping];
              lRetval = expectedLabelSize.height;
          }
          else if (indexPath.section == 2)
          {
              expectedLabelSize = [thirdcellText sizeWithFont:[UIFont systemFontOfSize:16.0]
                                             constrainedToSize:CGSizeMake(231, numberoflines*17.0)
                                                 lineBreakMode:NSLineBreakByWordWrapping];
              lRetval = expectedLabelSize.height-128.0;
          }
      
          UIImage *factoryImage = [UIImage imageNamed:NSLocalizedString(@"barcode_factory_reset.png", @"")];
      
          CGFloat height = factoryImage.size.height;
      
          if (lRetval < height) {
              lRetval = height+15.0;
          }
      
          return lRetval;
      }
      

      尝试在你的customcell类自动布局方法中添加如下代码

      textview.frame = frame;
      CGRect frame1 = textview.frame;
      frame1.size.height = textview.contentSize.height-2;
      textview.frame = frame1;
      
      
      textview.contentSize = CGSizeMake(textview.frame.size.width, textview.frame.size.height);
      
      labelPtr.frame = CGRectMake(CGRectGetMinX(imageView.frame)+CGRectGetMaxX(imageView.frame)+5.0, textview.frame.size.height+10.0, 140, 16.0);
      [labelPtr setNeedsDisplayInRect:labelPtr.frame];
      

      尝试如下设置标签属性

      labelPtr = [[UILabel alloc] initWithFrame:CGRectZero];
      labelPtr.backgroundColor =[UIColor clearColor];
      [labelPtr setNeedsLayout];
      [labelPtr setNeedsDisplay];
      [self.contentView addSubview:labelPtr];
      

      【讨论】:

      • 别担心thirdcellText 它是一个带有文本初始化的nsstring
      • 在哪里初始化thirdcellText?
      • 如果您有需要计算高度的文本,那么您可以检索并分配给thirdcellText。您可以仅在heightforrowatindexpath: 方法中分配文本..
      • 如果你有你要添加的文本的文本视图,那么上面的代码将会很有用。
      • 我使用的是 Label 而不是 TextView
      【解决方案4】:

      现在很简单
      使用以下步骤

      1. 为您的标签设置约束(如果使用自定义单元格)
      2. 行数必须为0
      3. 设置 UITableView 的几个属性

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

      享受:)
      更多详情可以查看
      www.raywenderlich.com
      stackoverflow.com

      【讨论】:

      【解决方案5】:

      我看到了很多解决方案,但都是错误的或不完整的。 你可以用 viewDidLoad 和 autolayout 中的 5 行来解决所有问题。 这对于目标 C:

      _tableView.delegate = self;
      _tableView.dataSource = self;
      self.tableView.estimatedRowHeight = 80;//the estimatedRowHeight but if is more this autoincremented with autolayout
      self.tableView.rowHeight = UITableViewAutomaticDimension;
      [self.tableView setNeedsLayout];
      [self.tableView layoutIfNeeded];
      self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0) ;
      

      对于 swift 2.0:

       self.tableView.estimatedRowHeight = 80
       self.tableView.rowHeight = UITableViewAutomaticDimension      
       self.tableView.setNeedsLayout()
       self.tableView.layoutIfNeeded()
       self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0)
      

      现在使用 xib 或在 Storyboard 中的 tableview 中创建您的单元格 有了这个,您无需再实施或覆盖。 (不要忘记数字 os 行 0)和底部标签(约束)降级“Content Hugging Priority -- Vertical to 250”

      您可以在下一个 url 中下载代码: https://github.com/jposes22/exampleTableCellCustomHeight

      参考:http://candycode.io/automatically-resizing-uitableviewcells-with-dynamic-text-height-using-auto-layout/

      【讨论】:

      • 我正在使用 swift,您的解决方案在支持 ios 9.0 的设备上完美运行。但是,当在带有 ios7.1 的设备上运行它时,单元格会变得不可见。你能@Jose Pose S 帮帮我吗?
      • 很抱歉,对于 iOS 7,我无法为您提供帮助 :(,因为从 iOS 8 开始,自动布局已更改。您可以将其与 Objective-C 或 swift 一起使用,但与 iOS 8 或更高版本一起使用.
      • 这是swift 2.3中的示例代码github.com/dpakthakur/DynamicCellHeight
      • 所有版本的 Swift 和 iOS 8 或更高版本的代码都是一样的
      【解决方案6】:

      请看HERE - 动态表格视图单元格高度和自动布局教程。

      你需要什么:

      • 对单元格中的元素设置所需的约束(确保所有操作都正确完成,如果没有 - 你会遇到很多问题)。还要确保将 IntrinsicSize 设置为 PlaceHolder 值

      • 添加一些计算单元格大小的方法

      方法:

      //this will calculate required height for your cell
      -(CGFloat)heightForBasicCellAtIndexPath:(NSIndexPath *)indexPath {
            static UIYourClassCellName *sizingCell = nil;
            //create just once per programm launching
            static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
            sizingCell = [self.tableView dequeueReusableCellWithIdentifier:@"identifierOfCell"];
      });
        [self configureBasicCell:sizingCell atIndexPath:indexPath];
        return [self calculateHeightForConfiguredSizingCell:sizingCell];
      }
      //this method will calculate required height of cell
      - (CGFloat)calculateHeightForConfiguredSizingCell:(UITableViewCell *)sizingCell {
            [sizingCell setNeedsLayout];
            [sizingCell layoutIfNeeded];
            CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
            return size.height;
      }
      

      然后调用

      - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        return [self heightForBasicCellAtIndexPath:indexPath];
      }
      

      单元格配置

      - (void)configureBasicCell:(RWBasicCell *)cell atIndexPath:(NSIndexPath *)indexPath {
          //make some configuration for your cell
      }
      

      完成所有操作后,我得到了下一个(单元格内的文本仅作为占位符):

      【讨论】:

      【解决方案7】:

      你可以试试这个吗?

      - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
          {
           int topPadding = cell.yourLabel.frame.origin.x;
           int bottomPadding = cell.frame.size.heigth-(topPadding+cell.yourLabel.frame.size.height);
           NSString *text = [DescArr objectAtIndex:[indexPath row]];
           CGSize maximumSize = CGSizeMake(cell.yourLabel.frame.size.width, 9999);
           CGSize expectedSize = [text sizeWithFont:yourCell.yourLabel.font constrainedToSize:maximumSize lineBreakMode:yourCell.yourLabel.lineBreakMode];
      
           return topPadding+expectedSize.height+bottomPadding;
      }
      

      【讨论】:

      • 单元格文本被覆盖
      • 在 .xib 中,选择大小动态变化的标签,然后在文件检查器下选择 Autosizing 的所有内容。
      【解决方案8】:

      一直在寻找如何正确确定单元格高度 - 看起来 - 这是一个最佳解决方案,boundingRectWithSize 和 constrainedToSize 经常错误计算文本高度,您需要创建 UILabel 而不是使用 sizeThatFits 函数,见下文

      - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
          {
      
          UILabel  * label = [[UILabel alloc] initWithFrame:CGRectMake(8, 5, celllabelWidth, 9999)];
          label.numberOfLines=0;
          label.font = [UIFont fontWithName:fontName size:textSize];
          label.text = @"celllabelTextHere";
      
          CGSize maximumLabelSize = CGSizeMake(celllabelWidth, 9999);
          CGSize expectedSize = [label sizeThatFits:maximumLabelSize];
          return expectedSize.height;
      }
      

      【讨论】:

        【解决方案9】:

        我刚刚写了关于这个问题以及我最终选择的方法。你可以在这里阅读:Dynamic UITableView Cell Height Based on Contents

        基本上,我创建了一个 UITableView 子类来处理默认和自定义单元格的所有这些。它可能需要调整,但我按原样使用它,效果很好。

        您可以在这里获取代码:https://github.com/danielsaidi/DSTableViewWithDynamicHeight

        希望它有所帮助(...如果没有,我很抱歉,并很想听听为什么不这样做)

        【讨论】:

          【解决方案10】:

          Refer this link you are using Autolayout

          否则你可以使用下面的方法

          - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
          
          
          NewsVCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
          
          if (cell == nil)
          {
          
              cell = [[NewsVCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
          
          }
          
          cell.titleCell.numberOfLines = 0;
          cell.descriptionCell.numberOfLines = 0;
          
          cell.titleCell.font = [UIFont systemFontOfSize:12.0f];
          cell.descriptionCell.font = [UIFont systemFontOfSize:12.0f];
          
          cell.descriptionCell.textColor = [UIColor lightGrayColor];
          
          
          CGSize maximumLabelSize;
          
          if([UIDevice currentDevice].userInterfaceIdiom==UIUserInterfaceIdiomPad || [[[UIDevice currentDevice] model] isEqualToString:@"iPad Simulator"])
          {
              maximumLabelSize = CGSizeMake(768, 10000);
          
          }
          else
          {
              maximumLabelSize = CGSizeMake(270, 10000);
          
          }
          
          NSString *newsTitle =  [[feeds objectAtIndex:indexPath.row] objectForKey: @"title"];
          
          NSString *descriptionsText = [[feeds objectAtIndex:indexPath.row] objectForKey: @"description"];
          
          
          CGSize expectedTitleLabelSize = [newsTitle sizeWithFont: cell.titleCell.font constrainedToSize:maximumLabelSize lineBreakMode:cell.titleCell.lineBreakMode];
          
          CGSize expectedDescriptionLabelSize = [descriptionsText sizeWithFont:cell.descriptionCell.font constrainedToSize:maximumLabelSize lineBreakMode:cell.descriptionCell.lineBreakMode];
          
          NSLog(@"cellForRowAtIndexPath :indexpath.row %d: height expectedTitleLabelSize:%f , indexpath.row height expectedDescriptionLabelSize:%f",indexPath.row,expectedTitleLabelSize.height,expectedDescriptionLabelSize.height);
          
          
          
          if (newsTitle.length > 0)
          {
          
              cell.titleCell.frame = CGRectMake(20.0f, 10.0f, 270.0f ,expectedTitleLabelSize.height+20.0f);
          
          }
          else
          {
               cell.titleCell.frame = CGRectMake(20.0f, 10.0f, 270.0f ,expectedTitleLabelSize.height-20.0f);
          }
          
          
          if (descriptionText.length > 0)
          {
              cell.descriptionCell.frame =  CGRectMake(20.0f, 10.0f + cell.titleCell.frame.size.height, 270.0f, expectedDescriptionLabelSize.height+20.0f);
          
          }
          else
          {
              cell.descriptionCell.frame =  CGRectMake(20.0f, cell.titleCell.frame.size.height, 270.0f, 0.0f);
          
          }
          
          
            cell.descriptionCell.frame =  CGRectMake(20.0f, 10.0f + cell.titleCell.frame.size.height, 270.0f, expectedDescriptionLabelSize.height+20.0f);
          
          cell.titleCell.text = newsTitle;
          cell.descriptionCell.text = descriptionsText;
          
          NSLog(@"indexpath.row %d :title %@ ",indexPath.row,newsTitle);
          
          NSLog(@"indexpath.row %d :description %@",indexPath.row,descriptionsText);
          
          return cell;
          
           }
          

          pragma mark - UITableViewDelegate

             - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
           {
          float totalHeight = 0.0f;
          
          UILabel *labelTitle;
          
          
          CGSize maximumLabelSize;
          
          
          if([UIDevice currentDevice].userInterfaceIdiom==UIUserInterfaceIdiomPad || [[[UIDevice currentDevice] model] isEqualToString:@"iPad Simulator"])
          {
              labelTitle = [[UILabel alloc]initWithFrame:CGRectMake(0.0f, 0.0f, 692.0f, 20.0f)];  // iPad
              maximumLabelSize = CGSizeMake(768.0f, 10000.0f);
          
          }
          else
          {
              labelTitle = [[UILabel alloc]initWithFrame:CGRectMake(0.0f, 0.0f, 270.0f, 20.0f)];
              maximumLabelSize = CGSizeMake(270.0f, 10000.0f);
          
          }
          
          
          
          labelTitle.font = [UIFont systemFontOfSize:12.0f];
          
          
          NSString *newsTitle;
          NSString *newsDescription;
          
            //  cell.titleCell.text = [[feeds objectAtIndex:indexPath.row] objectForKey: @"title"];
            //   cell.descriptionCell.text = [[feeds objectAtIndex:indexPath.row] objectForKey: @"description"];
          
          
          
              newsTitle = [[feeds objectAtIndex:indexPath.row] objectForKey: @"title"];
          
              newsDescription = [[feeds objectAtIndex:indexPath.row] objectForKey: @"description"];
          
          NSLog(@"indexpath.row %d :newsDescription.length %d",indexPath.row,newsDescription.length);
          CGSize expectedTitleLabelSize;
          CGSize expectedDescriptionLabelSize;
          
          
          if (newsTitle.length > 0)
          {
              expectedTitleLabelSize = [newsTitle sizeWithFont:labelTitle.font constrainedToSize:maximumLabelSize lineBreakMode:labelTitle.lineBreakMode];
              totalHeight = totalHeight + 20.0f;
          }
          else
          {
              expectedTitleLabelSize = CGSizeMake(0.0f, 0.0f);
              totalHeight = -20.0f;
          }
          
          if (newsDescription.length > 0)
          {
              expectedDescriptionLabelSize = [newsDescription sizeWithFont:labelTitle.font constrainedToSize:maximumLabelSize lineBreakMode:labelTitle.lineBreakMode];
              totalHeight = totalHeight + 20.0f;
          
          }
          else
          {
              expectedDescriptionLabelSize = CGSizeMake(0.0f, 0.0f);
              totalHeight = -20.0f;
          }
          
          
          //  NSLog(@"question: %f title:%f",expectedQuestionLabelSize.height,expectedTitleLabelSize.height);
          
          totalHeight = expectedDescriptionLabelSize.height + expectedTitleLabelSize.height + 30.0f+20.0f;
          
          
          
          
          return totalHeight;
          
           }
          

          【讨论】:

            【解决方案11】:

            如果要将最大高度限制为 100 pt,则必须在 MAX 上使用 MIN:

            CGFloat height = fmin(size.height, 100.0);
            

            【讨论】:

              【解决方案12】:

              我需要一个基于该单元格中显示的文本数量的动态表格视图单元格高度。我是这样解决的:

                  - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
                  {
                      if (!isLoading)
                      {
              
                          if ([self.conditionsDataArray count]>0)
                          {
                              Conditions *condition =[self.conditionsDataArray objectAtIndex:indexPath.row];
                              int height;
                              UITextView *textview = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 236, 0)];   //you can set your frame according to your need
                              textview.text  = condition.comment;
                              textview.autoresizingMask = UIViewAutoresizingFlexibleHeight;
                              [tableView addSubview:textview];
                              textview.hidden = YES;
                              height = textview.contentSize.height;
                              NSLog(@"TEXT VIEW HEIGHT %f", textview.contentSize.height);
                              [textview removeFromSuperview];
                              [textview release];
                              return height;
                     }
                     return 55;  //Default height, if data is in loading state
              }
              

              请注意,Text View 已添加为 Subview,然后被隐藏,因此请确保将其添加为 SubView,否则将不会考虑它的高度。

              【讨论】:

              • 哇哦。不要这样做。这种方法应该很快,并且不应该包含任何视图层次结构修改。
              • @allprog:在性能上没有妥协,我已经成功使用了这个方法,它在我的应用程序中运行顺利
              • 如果你这么说。我还没试过,但你让我很好奇。 UITableView 在这方面似乎有点坏,因为它要求高度然后是内容。我确信这是由于一些优化,但在当前情况下,它需要计算两次。
              • 这里是swift 2.3中的示例代码github.com/dpakthakur/DynamicCellHeight
              猜你喜欢
              • 1970-01-01
              • 2012-10-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-08-30
              • 1970-01-01
              相关资源
              最近更新 更多