使用自动布局约束在iOS UITableView中实现可变单元格高度

3
我有一个视图控制器,其中包含一个UITableView实例,并使用自动布局约束来呈现它。我希望在这个表格视图中拥有可变的单元格高度。我不想自己计算单元格高度,因为我的复杂单元格内容由几个标签和图片组成,而这些内容在每个单元格中都可能不同。我相信可以让自动布局单元格自行调整大小,以容纳所有子视图(即在标签分配文本后使用sizeToFit方法?)。
我有一个自定义单元格类,它使用自动布局的可视化约束格式来定位其子视图。我尝试将此处提出的方法和其示例实现此处融合进去。
当我初始化表格视图时,我创建了一个与我的数据行长度相等的数组,并通过为MyCustomCell类型的原型单元格分配值并检索其高度来计算每行的高度。
[cell systemLayoutSizeFittingSize:UILayoutFittingExpandedSize].height

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

然而,执行所有这些操作后,我在xCode中遇到了无法阅读的异常NSInternalInconsistencyException,显示“Cannot find an outgoing row head for incoming head MyCustomCell:0xa8a1430.Width, which should never happen.”

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

    _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]];
3个回答

0
我使用了这段代码来动态计算每行的高度,因为每一行的内容都不同:
-(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);
    }

}

希望能有所帮助。


0

当我在Storyboard中直接将表视图单元格作为原型添加到UITableView中,并使用dequeueReusableCellWithIdentifier:获取单元格以缓存高度时,我遇到了这个问题。

如果我将单元格移动到单独的nib中,那么它将直接从nib实例化单元格以确定高度,问题就解决了。

然后,您可以向UITableView注册nib。希望这可以帮助您。


0
  • 指定并实现tableview的dataSource和delegate
  • UITableViewAutomaticDimension赋值给rowHeight和estimatedRowHeight
  • 实现delegate/dataSource方法(例如heightForRowAt)并返回一个UITableViewAutomaticDimension

-

Objective 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;
}

Swift:

@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(并将换行模式设置为截断尾部)
  • 相对于其父视图/单元格容器设置所有约束(顶部,底部,右侧和左侧)。
  • 可选:如果您希望标签覆盖最小垂直区域,即使没有数据,请设置标签的最小高度。

enter image description here

注意: 如果您有多个具有动态长度的标签(UI元素),应根据其内容大小进行调整: 为您希望以更高优先级扩展/压缩的标签调整“内容吸附和压缩阻力优先级”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接