当我使用自动布局来选择每个单元格的高度(因此它们是动态的)时,它主要工作,但有些单元格有点短。为啥是这样?

Posted

技术标签:

【中文标题】当我使用自动布局来选择每个单元格的高度(因此它们是动态的)时,它主要工作,但有些单元格有点短。为啥是这样?【英文标题】:When I use Auto Layout to choose each cell's height (so they're dynamic) it mostly works, but some cells are a little short. Why is this?当我使用自动布局来选择每个单元格的高度(因此它们是动态的)时,它主要工作,但有些单元格有点短。为什么是这样? 【发布时间】:2013-12-01 03:29:34 【问题描述】:

示例项目: http://cl.ly/2j0A1J203f3h

我正在尝试使用自动布局来动态确定每个单元格的高度,以便某些单元格可以容纳比其他单元格更多的内容。为此,我使用this *** answer 和accompanying GitHub example。

我在 Storyboard 中创建了一个名为 CSPostCellUITableViewCell 子类,并将 UILabel 放入标签中,其中最多包含 5 行文本。

仅出于示例目的,我在表格中只有两个单元格,因此在 cellForRowAtIndexPath: 中设置的标签有两个不同的文本(一个更长):

- (CSPostCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    CSPostCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SelfPostCell" forIndexPath:indexPath];
    cell.postTitle.text = indexPath.row == 0 ? @"Short title" : @"Long long long title. Holy crap this is one long title. When does it end? Oh right now.";
    [cell setNeedsUpdateConstraints];

    return cell;

然后我返回每个单元格的高度:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
    CSPostCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SelfPostCell"];

    cell.postTitle.text = indexPath.row == 0 ? @"Short title" : @"Long long long title. Holy crap this is one long title. When does it end? Oh right now.";
    cell.postTitle.preferredMaxLayoutWidth = tableView.bounds.size.width - 40;

    [cell setNeedsUpdateConstraints];
    [cell updateConstraintsIfNeeded];
    [cell.contentView setNeedsLayout];
    [cell.contentView layoutIfNeeded];

    CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    return height;

这或多或少与GitHub repo example 完全相同。

但是,当我在模拟器中运行应用程序时,它并不能正常工作。高度是动态的,可以针对较长的文本进行调整,但不足以使文本不会被截断。见下图:

在上述情况下,第二个单元格的标签应该显示另一行来结束文本,但它被切断了。

为什么没有显示所有的文字?

【问题讨论】:

【参考方案1】:

这个简化的代码对我来说效果很好,只有一点点 2 分。所有对 updateConstraints 的调用似乎都是不必要的。我不确定你为什么需要软糖因素——也许标签中有一些填充物?我用不同长度的字符串和不同的字体大小对其进行了测试,它总是能正常工作。

- (CSPostCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    CSPostCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SelfPostCell" forIndexPath:indexPath];
    cell.postTitle.text = indexPath.row == 0 ? @"Short title" : @"Long long long title. Holy crap this is one long title. When does it end? Oh right now.";
    return cell;


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
    CSPostCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SelfPostCell"];
    cell.postTitle.text = indexPath.row == 0 ? @"Short title" : @"Long long long title. Holy crap this is one long title. When does it end? Oh right now.";
    cell.postTitle.preferredMaxLayoutWidth = tableView.bounds.size.width - 40;
    CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    return height + 2;

【讨论】:

我不确定为什么所有不同的 updateConstraints 都存在,但它们 seem to be necessary 另请参阅 GitHub 示例。什么是软糖因素,是您添加的 2 点吗?有趣的是,感谢您的解决方案。很奇怪,它不能“开箱即用”,但不需要调整幻数。 @DougSmith,您尝试时是否需要它们?当我将它们全部删除时,它没有任何区别。是的,+2 是我添加的软糖因素。 通过添加+2,您正在计算单元格分隔符的高度。其实+1就够了。如果不显示单元格分隔符(UITableViewCellSeparatorStyleNone),则直接使用高度值,无需修改。 return height +1 用于分隔符。更灵活的方法是CGFloat separator = ((UITableViewCellSeparatorStyleNone != self.tableView.separatorStyle) ? 1 : 0); return height + separator;

以上是关于当我使用自动布局来选择每个单元格的高度(因此它们是动态的)时,它主要工作,但有些单元格有点短。为啥是这样?的主要内容,如果未能解决你的问题,请参考以下文章

使用自动布局自定义集合视图单元格的动态高度

具有动态大小的单元格的复杂自动布局

使用自动布局让文本视图占据整个单元格

iOS6 自动布局异常

当单元格的高度略微增长时,为啥我的标签不遵守我的自动布局约束?

UITableViewCell 扩展自动布局