【问题标题】:Setting custom UITableViewCells height设置自定义 UITableViewCells 高度
【发布时间】:2010-10-04 10:04:34
【问题描述】:

我正在使用一个自定义 UITableViewCell,它有一些要显示的标签、按钮和图像视图。单元格中有一个标签,其文本是NSString 对象,并且字符串的长度可以是可变的。因此,我无法在UITableViewheightForCellAtIndex 方法中为单元格设置恒定高度。单元格的高度取决于标签的高度,可以使用NSStringsizeWithFont 方法确定。我尝试使用它,但看起来我在某个地方出错了。怎么解决?

这是用于初始化单元格的代码。

if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier])
{
    self.selectionStyle = UITableViewCellSelectionStyleNone;
    UIImage *image = [UIImage imageNamed:@"dot.png"];
    imageView = [[UIImageView alloc] initWithImage:image];
    imageView.frame = CGRectMake(45.0,10.0,10,10);

    headingTxt = [[UILabel alloc] initWithFrame:   CGRectMake(60.0,0.0,150.0,post_hdg_ht)];
    [headingTxt setContentMode: UIViewContentModeCenter];
    headingTxt.text = postData.user_f_name;
    headingTxt.font = [UIFont boldSystemFontOfSize:13];
    headingTxt.textAlignment = UITextAlignmentLeft;
    headingTxt.textColor = [UIColor blackColor];

    dateTxt = [[UILabel alloc] initWithFrame:CGRectMake(55.0,23.0,150.0,post_date_ht)];
    dateTxt.text = postData.created_dtm;
    dateTxt.font = [UIFont italicSystemFontOfSize:11];
    dateTxt.textAlignment = UITextAlignmentLeft;
    dateTxt.textColor = [UIColor grayColor];

    NSString * text1 = postData.post_body;
    NSLog(@"text length = %d",[text1 length]);
    CGRect bounds = [UIScreen mainScreen].bounds;
    CGFloat tableViewWidth;
    CGFloat width = 0;
    tableViewWidth = bounds.size.width/2;
    width = tableViewWidth - 40; //fudge factor
    //CGSize textSize = {width, 20000.0f}; //width and height of text area
    CGSize textSize = {245.0, 20000.0f}; //width and height of text area
    CGSize size1 = [text1 sizeWithFont:[UIFont systemFontOfSize:11.0f]
                        constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap];

    CGFloat ht = MAX(size1.height, 28);
    textView = [[UILabel alloc] initWithFrame:CGRectMake(55.0,42.0,245.0,ht)];
    textView.text = postData.post_body;
    textView.font = [UIFont systemFontOfSize:11];
    textView.textAlignment = UITextAlignmentLeft;
    textView.textColor = [UIColor blackColor];
    textView.lineBreakMode = UILineBreakModeWordWrap;
    textView.numberOfLines = 3;
    textView.autoresizesSubviews = YES;

    [self.contentView addSubview:imageView];
    [self.contentView addSubview:textView];
    [self.contentView addSubview:webView];
    [self.contentView addSubview:dateTxt];
    [self.contentView addSubview:headingTxt];
    [self.contentView sizeToFit];

    [imageView release];
    [textView release];
    [webView release];
    [dateTxt release];
    [headingTxt release];
}

这是高度和宽度出错的标签:

textView = [[UILabel alloc] initWithFrame:CGRectMake(55.0,42.0,245.0,ht)];

【问题讨论】:

    标签: ios objective-c uitableview row-height


    【解决方案1】:

    您的UITableViewDelegate 应该实现tableView:heightForRowAtIndexPath:

    Objective-C

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

    斯威夫特 5

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return indexPath.row * 20
    }
    

    您可能希望使用NSStringsizeWithFont:constrainedToSize:lineBreakMode: 方法来计算行高,而不是仅仅在 indexPath 上执行一些愚蠢的数学运算:)

    【讨论】:

    • 你不是说[indexPath row] + 20吗?
    • Fulvio:不,关键是要让行的高度明显不同。
    • 设置为特定高度(例如,44 像素):返回 44;
    • 您能否提供更多有关如何使用此 sizeWithFont:constrainedToSize:lineBreakMode: 的详细信息?我的单元格中有一个 textView,我想在 heightForRowAtIndexPath: 中获取它的高度,以便设置行的高度,但我不知道如何获取它!谢谢
    • 如果您返回“[index row] * (some-value)”,那么第一个单元格可能不可见,因为它返回的第一个值为零。因此,最好计算所需的单元格高度并在此处返回计算值以使所有单元格可见
    【解决方案2】:

    如果所有行的高度相同,只需设置 UITableView 的 rowHeight 属性,而不是实现 heightForRowAtIndexPath。苹果文档:

    使用 tableView:heightForRowAtIndexPath: 代替 rowHeight 会影响性能。每次显示表视图时,它都会在委托上为其每一行调用 tableView:heightForRowAtIndexPath:,这可能会导致具有大量行(大约 1000 或更多)的表视图出现严重的性能问题。

    【讨论】:

    • 当所有行都具有相同的高度时,这非常有效。但是,原始发布者没有这种情况,因此答案本身并不错误,但没有回答原始问题。 但是我发现设置 rowHeight 最有可能产生 更好 性能 比覆盖 heightForRowAtIndexPath 因为像计算滚动条尺寸这样的事情是 O(1 ) 而不是 O(n) 在这种情况下。
    • 还要注意(出于显而易见的原因),如果设置了tableView.rowHeight,则不会调用heightForRowAtIndexPath,以防您试图找出原因(就像我一样)。
    【解决方案3】:

    在自定义 UITableViewCell -controller 中添加这个

    -(void)layoutSubviews {  
    
        CGRect newCellSubViewsFrame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
        CGRect newCellViewFrame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height);
    
        self.contentView.frame = self.contentView.bounds = self.backgroundView.frame = self.accessoryView.frame = newCellSubViewsFrame;
        self.frame = newCellViewFrame;
    
        [super layoutSubviews];
    }
    

    在 UITableView -controller 中添加这个

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return [indexPath row] * 1.5; // your dynamic height...
    }
    

    【讨论】:

    • CGRect newCellSubViewsFrame = self.bounds; CGRect newCellViewFrame = self.frame;
    【解决方案4】:
    #define FONT_SIZE 14.0f
    #define CELL_CONTENT_WIDTH 300.0f
    #define CELL_CONTENT_MARGIN 10.0f
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath      *)indexPath;
    {
       /// Here you can set also height according to your section and row
       if(indexPath.section==0 && indexPath.row==0)
       {
         text=@"pass here your dynamic data";
    
         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, 44.0f);
    
         return height + (CELL_CONTENT_MARGIN * 2);
       }
       else
       {
          return 44;
       }
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell;
        UILabel *label = nil;
    
        cell = [tv dequeueReusableCellWithIdentifier:@"Cell"];
        if (cell == nil)
        {
           cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"Cell"];
        }
        ********Here you can set also height according to your section and row*********
        if(indexPath.section==0 && indexPath.row==0)
        {
            label = [[UILabel alloc] initWithFrame:CGRectZero];
            [label setLineBreakMode:UILineBreakModeWordWrap];
            [label setMinimumFontSize:FONT_SIZE];
            [label setNumberOfLines:0];
            label.backgroundColor=[UIColor clearColor];
            [label setFont:[UIFont systemFontOfSize:FONT_SIZE]];
            [label setTag:1];
    
            // NSString *text1 =[NSString stringWithFormat:@"%@",text];
    
            CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
    
            CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
    
            if (!label)
            label = (UILabel*)[cell viewWithTag:1];
    
    
            label.text=[NSString stringWithFormat:@"%@",text];
            [label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH          - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];
            [cell.contentView addSubview:label];
        }
    return cell;
    }
    

    【讨论】:

      【解决方案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

      【讨论】:

      • 在 2 天内,我将使用 chars ImageView 和其他 subtableview 放置更多具有相同单元格的图像,此方法始终有效。真的感谢 +1。
      • 太好了!!它也会对其他人有所帮助。谢谢:)
      • 所以,正如承诺的那样,这里有新代码和新图像。
      • 非常感谢...继续加油...-:)
      • 如果您以编程方式创建 UITableViewCell,则此解决方案不起作用,例如不使用界面生成器
      【解决方案6】:
      - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
      {
          CGSize constraintSize = {245.0, 20000}
          CGSize neededSize = [ yourText sizeWithFont:[UIfont systemFontOfSize:14.0f] constrainedToSize:constraintSize  lineBreakMode:UILineBreakModeCharacterWrap]
      if ( neededSize.height <= 18) 
      
         return 45
      else return neededSize.height + 45 
      //18 is the size of your text with the requested font (systemFontOfSize 14). if you change fonts you have a different number to use  
      // 45 is what is required to have a nice cell as the neededSize.height is the "text"'s height only
      //not the cell.
      
      }
      

      【讨论】:

        【解决方案7】:

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

        • 分配和实现 tableview 数据源和委托
        • UITableViewAutomaticDimension 分配给rowHeight 和estimatedRowHeight
        • 实现委托/数据源方法(即heightForRowAt 并向其返回值UITableViewAutomaticDimension

        -

        目标 C:

        // in ViewController.h
        #import <UIKit/UIKit.h>
        
        @interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
        
          @property IBOutlet UITableView * table;
        
        @end
        
        // in ViewController.m
        
        - (void)viewDidLoad {
            [super viewDidLoad];
            self.table.dataSource = self;
            self.table.delegate = self;
        
            self.table.rowHeight = UITableViewAutomaticDimension;
            self.table.estimatedRowHeight = UITableViewAutomaticDimension;
        }
        
        -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        
            return 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
            table.rowHeight = UITableViewAutomaticDimension
            table.estimatedRowHeight = UITableViewAutomaticDimension
        }
        
        
        
        // UITableViewAutomaticDimension calculates height of label contents/text
        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            return UITableViewAutomaticDimension
        }
        

        对于 UITableviewCell 中的标签实例

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

        注意:如果您有多个标签(UIElements)具有动态长度,应根据其内容大小进行调整:为您的标签调整'Content Hugging and Compression Resistance Priority'想要以更高的优先级展开/压缩。

        在此示例中,我设置了低拥抱和高抗压优先级,这导致为第二个(黄色)标签的内容设置更高的优先级/重要性。

        【讨论】:

          【解决方案8】:

          感谢所有关于这个主题的帖子,有一些非常有用的方法可以调整 UITableViewCell 的 rowHeight。

          这里是其他人的一些概念的汇编,这些概念在为 iPhone 和 iPad 构建时确实很有帮助。您还可以访问不同的部分并根据不同大小的视图进行调整。

          - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
          
          if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
          {
              int cellHeight = 0;
          
              if ([indexPath section] == 0) 
              {
                  cellHeight = 16;
                  settingsTable.rowHeight = cellHeight;
              }
              else if ([indexPath section] == 1)
              {
                  cellHeight = 20;
                  settingsTable.rowHeight = cellHeight;
              }
          
              return cellHeight;
          }
          else
          {
              int cellHeight = 0;
          
              if ([indexPath section] == 0) 
              {
                  cellHeight = 24;
                  settingsTable.rowHeight = cellHeight;
              }
              else if ([indexPath section] == 1)
              {
                  cellHeight = 40;
                  settingsTable.rowHeight = cellHeight;
              }
          
              return cellHeight;
          }
          return 0;
          } 
          

          【讨论】:

          • 在 XCode 中分析时,行“int cellHeight;”创建了一个逻辑错误,“未定义或垃圾值返回给调用者。”通过将 cellHeight 设置为 0,这修复了错误。如果您没有在类似于上述 if/else if 语句的 switch 语句中将 NSString 设置为 nil,也会出现此错误。
          【解决方案9】:

          要随着标签文本的增加动态单元格高度,首先需要计算高度,文本将在-heightForRowAtIndexPath委托方法中使用,并将其与其他标签的添加高度一起返回,图像(最大高度为文本+其他静态组件的高度)并在单元格创建中使用相同的高度。

          #define FONT_SIZE 14.0f
          #define CELL_CONTENT_WIDTH 300.0f  
          #define CELL_CONTENT_MARGIN 10.0f
          
          - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
          {
          
              if (indexPath.row == 2) {  // the cell you want to be dynamic
          
                  NSString *text = dynamic text for your label;
          
                  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, 44.0f);
          
                  return height + (CELL_CONTENT_MARGIN * 2);
              }
              else {
                  return 44; // return normal cell height
              }
          }
          
          - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
          
              static NSString *CellIdentifier = @"Cell";
          
              UILabel *label;
          
              UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
          
              if (cell == nil) {
                  cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] ;
              }
          
              label = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, 280, 34)];
          
              [label setNumberOfLines:2];
          
              label.backgroundColor = [UIColor clearColor];
          
              [label setFont:[UIFont systemFontOfSize:FONT_SIZE]];
          
              label.adjustsFontSizeToFitWidth = NO;
          
              [[cell contentView] addSubview:label];
          
          
              NSString *text = dynamic text fro your label;
          
              [label setText:text];
          
              if (indexPath.row == 2) {// the cell which needs to be dynamic 
          
                  [label setNumberOfLines:0];
          
                  CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
          
                  CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
          
                  [label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];
          
              }
              return  cell;
          }
          

          【讨论】:

          • @Tisho 你有没有测试过 Tisho 兄弟做否决票。仔细测试,它的工作原理兄弟!!!!
          • 我没有否决您的回答。我刚刚改进了格式。
          猜你喜欢
          • 1970-01-01
          • 2015-06-06
          • 2017-08-09
          • 2012-06-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多