【问题标题】:Variable cell height in iOS UITableView with auto layout constraints in codeiOS UITableView 中的可变单元格高度在代码中具有自动布局约束
【发布时间】:2013-07-07 06:23:46
【问题描述】:

我有一个视图控制器,它有一个 UITableView 实例并使用自动布局约束来呈现它。我想在这个表格视图中有可变的单元格高度。我不想自己计算单元格高度,因为我有一个复杂的单元格内容,由多个标签和图像组成,这些标签和图像可能因单元格而异。我确实相信可以让自动布局单元格调整自身大小,使其包含所有子视图(即在为它们分配文本后使用标签的 sizeToFit 方法?)。

我有一个自定义单元格类,它使用自动布局的视觉约束格式来定位其子视图。我尝试合并here 中提出的方法及其示例实现here

当我初始化表格视图时,我创建了一个与我的数据行长度相等的数组,并通过将值分配给 MyCustomCell 类型的原型单元格来计算每一行的高度,并使用它检索其高度

[cell systemLayoutSizeFittingSize:UILayoutFittingExpandedSize].height

并将其存储在 heights 数组中,以便稍后在表格视图的 heightForRowAtIndexPath 方法中使用它来检索各个单元格的正确单元格高度。

但是,在执行所有这些操作时,我最终在 xCode 中遇到了一个无法读取的异常 NSInternalInconsistencyException,其中“找不到传入头 MyCustomCell:0xa8a1430.Width 的传出行头,这永远不会发生。”

这是我的自定义单元格中子视图的初始化:

    _titleLabel = [[UILabel alloc] init];
    _titleLabel.font = [TSTheme boldThemeFontOfSize:TSThemeFontSizeSmall];
    _titleLabel.textColor = [[TSTheme sharedTheme] darkTextColor];
    _titleLabel.backgroundColor = [UIColor clearColor];
    _titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
    _titleLabel.font = [UIFont fontWithName:@"HelveticaNeue-CondensedBold" size:19];
    _titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
    [self.contentView addSubview:_titleLabel];

    _summaryLabel = [[UILabel alloc] init];
    _summaryLabel.font = [TSTheme boldThemeFontOfSize:TSThemeFontSizeSmall];
    _summaryLabel.backgroundColor = [UIColor clearColor];
    _summaryLabel.textColor = [[TSTheme sharedTheme] darkTextColor];
    _summaryLabel.translatesAutoresizingMaskIntoConstraints = NO;
    _summaryLabel.numberOfLines = 0;
    _summaryLabel.preferredMaxLayoutWidth = 250.0f; // required for text wrapping
    _summaryLabel.font = [UIFont fontWithName:@"Georgia" size:14];
    _summaryLabel.lineBreakMode = NSLineBreakByWordWrapping;
    [self.contentView addSubview:_summaryLabel];

    _thumbnailView = [[UIImageView alloc] init];
    _thumbnailView.translatesAutoresizingMaskIntoConstraints = NO;

    [self.contentView addSubview:_thumbnailView];

我的自定义单元格的约束如下

NSDictionary *views = NSDictionaryOfVariableBindings(_titleLabel, _summaryLabel, _thumbnailView);
NSDictionary *metrics = @{@"margin": @"5"};

[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(margin)-[_thumbnailView(<=60)]-(margin)-[_titleLabel]-(margin)-|"
                                                                         options:0
                                                                         metrics:metrics
                                                                           views:views]];

[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(margin)-[_thumbnailView]-(margin)-|"
                                                                         options:0
                                                                         metrics:metrics
                                                                           views:views]];


[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(margin)-[_titleLabel]-(0)-[_summaryLabel]"
                                                                         options:0
                                                                         metrics:metrics
                                                                           views:views]];


[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(margin)-[_thumbnailView]-(margin)-[_summaryLabel]-(margin)-|"
                                                                         options:0
                                                                         metrics:metrics
                                                                           views:views]];

【问题讨论】:

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


    【解决方案1】:

    当我使用一个表格视图单元格时遇到这种情况,该单元格直接作为原型添加到情节提要中的 UITableView 并使用 dequeueReusableCellWithIdentifier: 获取用于缓存高度的单元格。

    如果我将单元格移动到单独的笔尖,那么它会实例化单元格以直接从笔尖确定高度,问题就消失了。

    然后你可以用 UITableView 注册 nib。希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      我使用这段代码来动态计算一行的高度,因为每行的内容不同:

      -(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ // Hacer que el tamaño de la celda sea variable dependiendo del tamaño del texto a mostrar
      
          NoticiaAsignatura_DTO *rowData = [[NoticiaAsignatura_DTO alloc] init];
      
          rowData = [self.listaNoticias objectAtIndex:[indexPath row]];
      
          NSString *text = rowData.title;
          text = [text stringByAppendingString:@"\n"];
          text = [text stringByAppendingString: rowData.publish_date_ansi];
          text = [text stringByAppendingString:@"\n\n"];
          text = [text stringByAppendingString:rowData.content];
          text = [text stringByAppendingString:@"\n\n"];
      
          if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
      
              CGSize constraint = CGSizeMake(700,200000.0);
              CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
              return size.height + (CELL_CONTENT_MARGIN * 2);
          }
          else{
              CGSize constraint = CGSizeMake(300,200000.0);
              CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE_PHONE] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
              NSLog(@"Size: %f ", size.height);
              return size.height + (CELL_CONTENT_MARGIN * 2);
          }
      
      }
      

      希望对你有帮助。

      【讨论】:

        【解决方案3】:
        • 分配和实现 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'想要以更高的优先级展开/压缩。

        【讨论】:

          猜你喜欢
          • 2019-07-22
          • 2014-07-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-06-18
          • 2023-03-11
          • 2013-09-15
          相关资源
          最近更新 更多